[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] merge?



# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID 308260e5868ce792f1a1276c4b0a04305a128216
# Parent  cedb89d6b707071ba66fefe64b19925da9d68334
# Parent  8f9dfc5fb51c6110c3b59d53ee9f40dec90a58ba
merge?

diff -r cedb89d6b707 -r 308260e5868c docs/Makefile
--- a/docs/Makefile     Mon Sep 19 09:14:41 2005
+++ b/docs/Makefile     Mon Sep 19 10:51:05 2005
@@ -36,11 +36,12 @@
        $(MAKE) $(DOC_HTML); fi
 
 python-dev-docs:
-       mkdir -p api/tools/python
+       @mkdir -v -p api/tools/python
        @if which $(DOXYGEN) 1>/dev/null 2>/dev/null; then         \
         echo "Running doxygen to generate Python tools APIs ... "; \
        $(DOXYGEN) Doxyfile;                                       \
-       $(MAKE) -C api/tools/python/latex ; fi
+       $(MAKE) -C api/tools/python/latex ; else                   \
+        echo "Doxygen not installed; skipping python-dev-docs."; fi
 
 clean:
        rm -rf .word_count *.aux *.dvi *.bbl *.blg *.glo *.idx *~ 
diff -r cedb89d6b707 -r 308260e5868c tools/python/pylintrc
--- a/tools/python/pylintrc     Mon Sep 19 09:14:41 2005
+++ b/tools/python/pylintrc     Mon Sep 19 10:51:05 2005
@@ -74,7 +74,7 @@
 init-import=no
 
 # List of variable names used for dummy variables (i.e. not used).
-dummy-variables=_,dummy
+dummy-variables=_,_1,_2,_3,_4,_5,dummy
 
 
 
@@ -131,7 +131,7 @@
 bad-names=foo,bar,baz,toto,tutu,tata
 
 # List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter,apply,input
+bad-functions=apply,input
 
 
 
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/sv/Main.py
--- a/tools/python/xen/sv/Main.py       Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/sv/Main.py       Mon Sep 19 10:51:05 2005
@@ -1,5 +1,4 @@
 
-from xen.sv.HTMLBase import HTMLBase
 from xen.sv.NodeInfo import NodeInfo
 from xen.sv.DomInfo  import DomInfo
 from xen.sv.CreateDomain import CreateDomain
@@ -33,15 +32,8 @@
             result.append( (key, self.fieldStorage.getlist( key ) ) )
         return result
                                                                                
                                                                             
-class TwistedAdapter:
-    def __init__( self, req ):
-        self.args = Args( req )
-        self.uri = req.unparsed_uri
-        self.url = req.uri
-        self.write = req.write
-
 # This is the Main class
-# It peices together all the modules
+# It pieces together all the modules
 
 class Main:
     def __init__( self ):
@@ -61,7 +53,7 @@
             self.init_modules( request )
             self.init_done = True
             
-        for moduleName, module in self.modules.iteritems():
+        for _, module in self.modules.iteritems():
             module.write_MENU( request )
             request.write( "\n" )
 
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/sv/Wizard.py
--- a/tools/python/xen/sv/Wizard.py     Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/sv/Wizard.py     Mon Sep 19 10:51:05 2005
@@ -47,7 +47,7 @@
     def __init__( self, urlWriter, title, location ):
         HTMLBase.__init__( self )
         self.urlWriter = urlWriter
-        self.feilds = []
+        self.fields = []
         self.title = title
         self.location = location
         self.passback = None
@@ -86,9 +86,9 @@
         
         request.write( "<table width='100%' cellpadding='0' cellspacing='1' 
border='0'>" )
         
-       for (feild, control) in self.feilds:
-            control.write_Control( request, previous_values.get( feild ) )
-            if previous_values.get( feild ) is not None and not 
control.validate( previous_values.get( feild ) ):
+       for (field, control) in self.fields:
+            control.write_Control( request, previous_values.get( field ) )
+            if previous_values.get( field ) is not None and not 
control.validate( previous_values.get( field ) ):
                control.write_Help( request )
             
         request.write( "</table>" )
@@ -97,7 +97,7 @@
         #request.write( "<input type='hidden' name='visited-sheet%s' 
value='True'></p>" % self.location )
                 
     def addControl( self, control ):
-       self.feilds.append( [ control.getName(), control ] )
+       self.fields.append( [ control.getName(), control ] )
         
     def validate( self, request ):
     
@@ -108,10 +108,10 @@
         previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the 
map for quick reference
        if DEBUG: print previous_values
       
-       for (feild, control) in self.feilds:
-            if not control.validate( previous_values.get( feild ) ):
+       for (field, control) in self.fields:
+            if not control.validate( previous_values.get( field ) ):
                 check = False
-                if DEBUG: print "> %s = %s" % (feild, previous_values.get( 
feild ))
+                if DEBUG: print "> %s = %s" % (field, previous_values.get( 
field ))
 
         return check
         
@@ -143,7 +143,7 @@
         
 class InputControl( SheetControl ):
 
-    def __init__( self, name, defaultValue, humanText,  reg_exp = ".*", 
help_text = "You must enter the appropriate details in this feild." ):
+    def __init__( self, name, defaultValue, humanText,  reg_exp = ".*", 
help_text = "You must enter the appropriate details in this field." ):
         SheetControl.__init__( self, reg_exp )
         self.setName( name )
         
@@ -206,7 +206,7 @@
         
 class FileControl( InputControl ):
 
-    def __init__( self, name, defaultValue, humanText,  reg_exp = ".*", 
help_text = "You must enter the appropriate details in this feild." ):
+    def __init__( self, name, defaultValue, humanText,  reg_exp = ".*", 
help_text = "You must enter the appropriate details in this field." ):
        InputControl.__init__( self, name, defaultValue, humanText )
         
     def validate( self, persistedValue ):
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/Args.py
--- a/tools/python/xen/xend/Args.py     Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/Args.py     Mon Sep 19 10:51:05 2005
@@ -32,12 +32,12 @@
         self.arg_dict = {}
         self.key_ord = []
         self.key_dict = {}
-        for (name, type) in paramspec:
+        for (name, typ) in paramspec:
                 self.arg_ord.append(name)
-                self.arg_dict[name] = type
-        for (name, type) in keyspec:
+                self.arg_dict[name] = typ
+        for (name, typ) in keyspec:
                 self.key_ord.append(name)
-                self.key_dict[name] = type
+                self.key_dict[name] = typ
 
     def get_args(self, d, xargs=None):
         args = {}
@@ -56,12 +56,12 @@
     def split_args(self, d, args, keys):
         for (k, v) in d.items():
             if k in self.arg_dict:
-                type = self.arg_dict[k]
-                val = self.coerce(type, v)
+                typ = self.arg_dict[k]
+                val = self.coerce(typ, v)
                 args[k] = val
             elif k in self.key_dict:
-                type = self.key_dict[k]
-                val = self.coerce(type, v)
+                typ = self.key_dict[k]
+                val = self.coerce(typ, v)
                 keys[k] = val
             else:
                 raise ArgError('Invalid parameter: %s' % k)
@@ -85,20 +85,20 @@
             d[k] = val
         return self.get_args(d, xargs=xargs)
 
-    def coerce(self, type, v):
+    def coerce(self, typ, v):
         try:
-            if type == 'int':
+            if typ == 'int':
                 val = int(v)
-            elif type == 'long':
+            elif typ == 'long':
                 val = long(v)
-            elif type == 'str':
+            elif typ == 'str':
                 val = str(v)
-            elif type == 'sxpr':
+            elif typ == 'sxpr':
                 val = self.sxpr(v)
-            elif type == 'bool':
+            elif typ == 'bool':
                 val = self.bool(v)
             else:
-                raise ArgError('invalid type:' + str(type))
+                raise ArgError('invalid type:' + str(typ))
             return val
         except ArgError:
             raise
@@ -142,7 +142,9 @@
     Used on the client.
     """
 
-    def __init__(self, fn, paramspec, keyspec={}):
+    def __init__(self, fn, paramspec, keyspec = None):
+        if keyspec == None:
+            keyspec = {}
         Args.__init__(self, paramspec, keyspec)
         self.fn = fn
 
@@ -154,7 +156,9 @@
     Used in the HTTP server.
     """
 
-    def __init__(self, fn, paramspec, keyspec={}):
+    def __init__(self, fn, paramspec, keyspec = None):
+        if keyspec == None:
+            keyspec = {}
         Args.__init__(self, paramspec, keyspec)
         self.fn = fn
 
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/EventServer.py
--- a/tools/python/xen/xend/EventServer.py      Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/EventServer.py      Mon Sep 19 10:51:05 2005
@@ -145,7 +145,7 @@
             self.lock.release()
             
         if async:
-            scheduler.now(self.call_handlers, [event, val])
+            scheduler.now(self.call_handlers, event, val)
         else:
             self.call_handlers(event, val)
 
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/Vifctl.py
--- a/tools/python/xen/xend/Vifctl.py   Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/Vifctl.py   Mon Sep 19 10:51:05 2005
@@ -13,13 +13,13 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
 
 """Xend interface to networking control scripts.
 """
 import os
 import os.path
-import sys
 import xen.util.process
 
 from xen.xend import XendRoot
@@ -71,7 +71,7 @@
         vif = vif_old
     return vif
 
-def vifctl(op, vif=None, script=None, domain=None, mac=None, bridge=None, 
ipaddr=[]):
+def vifctl(op, vif=None, script=None, domain=None, mac=None, bridge=None, 
ipaddr=None):
     """Call a vif control script.
     Xend calls this when bringing vifs up or down.
 
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/XendCheckpoint.py   Mon Sep 19 10:51:05 2005
@@ -83,7 +83,7 @@
     if child.wait() != 0:
         raise XendError("xc_save failed: %s" % lasterr)
 
-    dominfo.setStoreChannel(None)
+    dominfo.closeStoreChannel()
     xd.domain_destroy(dominfo.domid)
     return None
 
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/XendDomain.py       Mon Sep 19 10:51:05 2005
@@ -55,7 +55,7 @@
 class XendDomainDict(dict):
     def get_by_name(self, name):
         try:
-            return filter(lambda d: d.name == name, self.values())[0]
+            return filter(lambda d: d.getName() == name, self.values())[0]
         except IndexError, err:
             return None
 
@@ -94,7 +94,7 @@
         @return: domain objects
         """
         doms = self.list()
-        doms.sort(lambda x, y: cmp(x.name, y.name))
+        doms.sort(lambda x, y: cmp(x.getName(), y.getName()))
         return doms
 
     def list_names(self):
@@ -103,7 +103,7 @@
         @return: domain names
         """
         doms = self.list_sorted()
-        return map(lambda x: x.name, doms)
+        return map(lambda x: x.getName(), doms)
 
     def onReleaseDomain(self):
         self.reap()
@@ -183,12 +183,13 @@
         @param info:   domain info object
         @param notify: send a domain created event if true
         """
-        if info.domid in self.domains:
+        if info.getDomain() in self.domains:
             notify = False
-        self.domains[info.domid] = info
+        self.domains[info.getDomain()] = info
         info.exportToDB(save=True)
         if notify:
-            eserver.inject('xend.domain.create', [info.name, info.domid])
+            eserver.inject('xend.domain.create', [info.getName(),
+                                                  info.getDomain()])
 
     def _delete_domain(self, id, notify=True):
         """Remove a domain from the tables.
@@ -202,7 +203,8 @@
             info.cleanup()
             info.delete()
             if notify:
-                eserver.inject('xend.domain.died', [info.name, info.domid])
+                eserver.inject('xend.domain.died', [info.getName(),
+                                                    info.getDomain()])
         # XXX this should not be needed
         for domdb in self.dbmap.values():
             if not domdb.has_key("xend"):
@@ -227,13 +229,13 @@
             dominfo = self.domains.get(domid)
             if not dominfo or dominfo.is_terminated():
                 continue
-            log.debug('domain died name=%s domid=%d', dominfo.name, domid)
+            log.debug('domain died name=%s domid=%d', dominfo.getName(), domid)
             if d['crashed'] and xroot.get_enable_dump():
                 self.domain_dumpcore(domid)
             if d['shutdown']:
                 reason = shutdown_reason(d['shutdown_reason'])
-                log.debug('shutdown name=%s id=%d reason=%s', dominfo.name,
-                          domid, reason)
+                log.debug('shutdown name=%s id=%d reason=%s',
+                          dominfo.getName(), domid, reason)
                 if reason == 'suspend':
                     dominfo.state_set("suspended")
                     continue
@@ -248,11 +250,11 @@
         # Remove entries for domains that no longer exist.
         # Update entries for existing domains.
         for d in self.domains.values():
-            info = doms.get(d.domid)
+            info = doms.get(d.getDomain())
             if info:
                 d.update(info)
             elif not d.restart_pending():
-                self._delete_domain(d.domid)
+                self._delete_domain(d.getDomain())
 
     def update_domain(self, id):
         """Update information for a single domain.
@@ -281,20 +283,23 @@
 
         @param dominfo: domain object
         """
-        log.info("Restarting domain: name=%s id=%s", dominfo.name, 
dominfo.domid)
+        log.info("Restarting domain: name=%s id=%s", dominfo.getName(),
+                 dominfo.getDomain())
         eserver.inject("xend.domain.restart",
-                       [dominfo.name, dominfo.domid, "begin"])
+                       [dominfo.getName(), dominfo.getDomain(), "begin"])
         try:
             dominfo.restart()
-            log.info('Restarted domain name=%s id=%s', dominfo.name, 
dominfo.domid)
+            log.info('Restarted domain name=%s id=%s', dominfo.getName(),
+                     dominfo.getDomain())
             eserver.inject("xend.domain.restart",
-                           [dominfo.name, dominfo.domid, "success"])
-            self.domain_unpause(dominfo.domid)
+                           [dominfo.getName(), dominfo.getDomain(),
+                            "success"])
+            self.domain_unpause(dominfo.getDomain())
         except Exception, ex:
             log.exception("Exception restarting domain: name=%s id=%s",
-                          dominfo.name, dominfo.domid)
+                          dominfo.getName(), dominfo.getDomain())
             eserver.inject("xend.domain.restart",
-                           [dominfo.name, dominfo.domid, "fail"])
+                           [dominfo.getName(), dominfo.getDomain(), "fail"])
         return dominfo
 
     def domain_configure(self, vmconfig):
@@ -376,9 +381,10 @@
         @param id: domain id
         """
         dominfo = self.domain_lookup(id)
-        eserver.inject('xend.domain.unpause', [dominfo.name, dominfo.domid])
-        try:
-            return xc.domain_unpause(dom=dominfo.domid)
+        eserver.inject('xend.domain.unpause', [dominfo.getName(),
+                                               dominfo.getDomain()])
+        try:
+            return xc.domain_unpause(dom=dominfo.getDomain())
         except Exception, ex:
             raise XendError(str(ex))
     
@@ -388,9 +394,10 @@
         @param id: domain id
         """
         dominfo = self.domain_lookup(id)
-        eserver.inject('xend.domain.pause', [dominfo.name, dominfo.domid])
-        try:
-            return xc.domain_pause(dom=dominfo.domid)
+        eserver.inject('xend.domain.pause', [dominfo.getName(),
+                                             dominfo.getDomain()])
+        try:
+            return xc.domain_pause(dom=dominfo.getDomain())
         except Exception, ex:
             raise XendError(str(ex))
     
@@ -406,8 +413,9 @@
         @param reason: shutdown type: poweroff, reboot, suspend, halt
         """
         dominfo = self.domain_lookup(id)
-        self.domain_restart_schedule(dominfo.domid, reason, force=True)
-        eserver.inject('xend.domain.shutdown', [dominfo.name, dominfo.domid, 
reason])
+        self.domain_restart_schedule(dominfo.getDomain(), reason, force=True)
+        eserver.inject('xend.domain.shutdown', [dominfo.getName(),
+                                                dominfo.getDomain(), reason])
         if reason == 'halt':
             reason = 'poweroff'
         val = dominfo.shutdown(reason)
@@ -431,13 +439,13 @@
             if not dominfo.shutdown_pending:
                 # domain doesn't need shutdown
                 continue
-            id = dominfo.domid
+            id = dominfo.getDomain()
             left = dominfo.shutdown_time_left(SHUTDOWN_TIMEOUT)
             if left <= 0:
                 # Shutdown expired - destroy domain.
                 try:
                     log.info("Domain shutdown timeout expired: name=%s id=%s",
-                             dominfo.name, id)
+                             dominfo.getName(), id)
                     self.domain_destroy(id, reason=
                                         dominfo.shutdown_pending['reason'])
                 except Exception:
@@ -462,15 +470,16 @@
         restart = (force and reason == 'reboot') or 
dominfo.restart_needed(reason)
         if restart:
             log.info('Scheduling restart for domain: name=%s id=%s',
-                     dominfo.name, dominfo.domid)
+                     dominfo.getName(), dominfo.getDomain())
             eserver.inject("xend.domain.restart",
-                           [dominfo.name, dominfo.domid, "schedule"])
+                           [dominfo.getName(), dominfo.getDomain(),
+                            "schedule"])
             dominfo.restarting()
         else:
             log.info('Cancelling restart for domain: name=%s id=%s',
-                     dominfo.name, dominfo.domid)
+                     dominfo.getName(), dominfo.getDomain())
             eserver.inject("xend.domain.restart",
-                           [dominfo.name, dominfo.domid, "cancel"])
+                           [dominfo.getName(), dominfo.getDomain(), "cancel"])
             dominfo.restart_cancel()
 
     def domain_restarts(self):
@@ -480,12 +489,12 @@
         for dominfo in self.domains.values():
             if not dominfo.restart_pending():
                 continue
-            info = doms.get(dominfo.domid)
+            info = doms.get(dominfo.getDomain())
             if info:
                 # Don't execute restart for domains still running.
                 continue
             # Remove it from the restarts.
-            log.info('restarting: %s' % dominfo.name)
+            log.info('restarting: %s' % dominfo.getName())
             self.domain_restart(dominfo)
 
     def domain_destroy(self, domid, reason='halt'):
@@ -520,13 +529,14 @@
 
         # temporarily rename domain for localhost migration
         if dst == "localhost":
-            dominfo.name = "tmp-" + dominfo.name
+            dominfo.setName("tmp-" + dominfo.getName())
 
         try:
             XendCheckpoint.save(self, sock.fileno(), dominfo, live)
         except:
             if dst == "localhost":
-                dominfo.name = string.replace(dominfo.name, "tmp-", "", 1)
+                dominfo.setName(
+                    string.replace(dominfo.getName(), "tmp-", "", 1))
             raise
         
         return None
@@ -560,7 +570,7 @@
         """
         dominfo = self.domain_lookup(id)
         try:
-            return xc.domain_pincpu(dominfo.domid, vcpu, cpumap)
+            return xc.domain_pincpu(dominfo.getDomain(), vcpu, cpumap)
         except Exception, ex:
             raise XendError(str(ex))
 
@@ -569,8 +579,10 @@
         """
         dominfo = self.domain_lookup(id)
         try:
-            return xc.bvtsched_domain_set(dom=dominfo.domid, mcuadv=mcuadv,
-                                          warpback=warpback, 
warpvalue=warpvalue, 
+            return xc.bvtsched_domain_set(dom=dominfo.getDomain(),
+                                          mcuadv=mcuadv,
+                                          warpback=warpback,
+                                          warpvalue=warpvalue, 
                                           warpl=warpl, warpu=warpu)
         except Exception, ex:
             raise XendError(str(ex))
@@ -580,7 +592,7 @@
         """
         dominfo = self.domain_lookup(id)
         try:
-            return xc.bvtsched_domain_get(dominfo.domid)
+            return xc.bvtsched_domain_get(dominfo.getDomain())
         except Exception, ex:
             raise XendError(str(ex))
     
@@ -590,7 +602,8 @@
         """
         dominfo = self.domain_lookup(id)
         try:
-            return xc.sedf_domain_set(dominfo.domid, period, slice, latency, 
extratime, weight)
+            return xc.sedf_domain_set(dominfo.getDomain(), period, slice,
+                                      latency, extratime, weight)
         except Exception, ex:
             raise XendError(str(ex))
 
@@ -599,7 +612,7 @@
         """
         dominfo = self.domain_lookup(id)
         try:
-            return xc.sedf_domain_get(dominfo.domid)
+            return xc.sedf_domain_get(dominfo.getDomain())
         except Exception, ex:
             raise XendError(str(ex))
 
@@ -647,9 +660,8 @@
         @param type: device type
         """
         dominfo = self.domain_lookup(id)
-        val = dominfo.device_delete(type, devid)
-        dominfo.exportToDB()
-        return val
+        return dominfo.destroyDevice(type, devid)
+
 
     def domain_devtype_ls(self, id, type):
         """Get list of device sxprs for a domain.
@@ -689,7 +701,7 @@
         """
         dominfo = self.domain_lookup(id)
         try:
-            return xc.shadow_control(dominfo.domid, op)
+            return xc.shadow_control(dominfo.getDomain(), op)
         except Exception, ex:
             raise XendError(str(ex))
 
@@ -703,7 +715,8 @@
         dominfo = self.domain_lookup(id)
         maxmem = int(mem) * 1024
         try:
-            return xc.domain_setmaxmem(dominfo.domid, maxmem_kb = maxmem)
+            return xc.domain_setmaxmem(dominfo.getDomain(),
+                                       maxmem_kb = maxmem)
         except Exception, ex:
             raise XendError(str(ex))
 
@@ -735,12 +748,13 @@
         @param id: domain
         """
         dominfo = self.domain_lookup(id)
-        corefile = "/var/xen/dump/%s.%s.core"% (dominfo.name, dominfo.domid)
-        try:
-            xc.domain_dumpcore(dom=dominfo.domid, corefile=corefile)
+        corefile = "/var/xen/dump/%s.%s.core" % (dominfo.getName(),
+                                                 dominfo.getDomain())
+        try:
+            xc.domain_dumpcore(dom=dominfo.getDomain(), corefile=corefile)
         except Exception, ex:
             log.warning("Dumpcore failed, id=%s name=%s: %s",
-                        dominfo.domid, dominfo.name, ex)
+                        dominfo.getDomain(), dominfo.getName(), ex)
         
 def instance():
     """Singleton constructor. Use this instead of the class constructor.
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Mon Sep 19 10:51:05 2005
@@ -1,4 +1,4 @@
-#============================================================================
+#===========================================================================
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of version 2.1 of the GNU Lesser General Public
 # License as published by the Free Software Foundation.
@@ -23,23 +23,18 @@
 
 """
 
-import string, re
-import os
+import string
 import time
 import threading
 import errno
 
-import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
-from xen.util.ip import check_subnet, get_current_ipgw
+import xen.lowlevel.xc
 from xen.util.blkif import blkdev_uname_to_file
 
-from xen.xend.server import controller
-from xen.xend.server import SrvDaemon; xend = SrvDaemon.instance()
+from xen.xend.server import SrvDaemon
 from xen.xend.server.channel import EventChannel
-from xen.util.blkif import blkdev_name_to_number, expand_dev_name
 
 from xen.xend import sxp
-from xen.xend import Blkctl
 from xen.xend.PrettyPrint import prettyprintstring
 from xen.xend.XendBootloader import bootloader
 from xen.xend.XendLogging import log
@@ -47,7 +42,7 @@
 from xen.xend.XendRoot import get_component
 
 from xen.xend.uuid import getUuid
-from xen.xend.xenstore import DBVar, XenNode, DBMap
+from xen.xend.xenstore import DBVar
 from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.xenstore.xsutil import IntroduceDomain
 
@@ -96,6 +91,12 @@
 
 """Flag for a TPM device backend domain."""
 SIF_TPM_BE_DOMAIN = (1<<7)
+
+
+xc = xen.lowlevel.xc.new()
+
+
+xend = SrvDaemon.instance()
 
 
 def domain_exists(name):
@@ -248,11 +249,9 @@
         self.store_mfn = None
         self.console_channel = None
         self.console_mfn = None
-        self.controllers = {}
         
         self.info = None
         self.backend_flags = 0
-        self.netif_idx = 0
         
         #todo: state: running, suspended
         self.state = STATE_VM_OK
@@ -334,26 +333,50 @@
     def getName(self):
         return self.name
 
+    def getPath(self):
+        return self.path
+
+    def getUuid(self):
+        return self.uuid
+
+    def getVCpuCount(self):
+        return self.vcpus
+
+    def getSsidref(self):
+        return self.ssidref
+
+    def getMemoryTarget(self):
+        """Get this domain's target memory size, in MiB."""
+        return self.memory
+
     def setStoreRef(self, ref):
         self.store_mfn = ref
         self.storeDom("store/ring-ref", ref)
 
-    def setStoreChannel(self, channel):
-        if self.store_channel and self.store_channel != channel:
-            self.store_channel.close()
-        self.store_channel = channel
-        if channel:
-            port = channel.port1
-        else:
-            port = None
-        self.storeDom("store/port", None)
+
+    def getBackendFlags(self):
+        return self.backend_flags
+
+
+    def closeStoreChannel(self):
+        """Close the store channel, if any.  Nothrow guarantee."""
+        
+        try:
+            if self.store_channel:
+                try:
+                    self.store_channel.close()
+                    self.removeDom("store/port")
+                finally:
+                    self.store_channel = None
+        except Exception, exn:
+            log.exception(exn)
+
 
     def setConsoleRef(self, ref):
         self.console_mfn = ref
         self.storeDom("console/ring-ref", ref)
 
     def setMemoryTarget(self, target):
-        self.memory_target = target
         self.storeDom("memory/target", target)
 
     def update(self, info=None):
@@ -394,150 +417,26 @@
 
     __repr__ = __str__
 
-    def getDeviceController(self, type, error=True):
-        ctrl = self.controllers.get(type)
-        if not ctrl and error:
-            raise XendError("invalid device type:" + type)
-        return ctrl
-    
-    def findDeviceController(self, type):
-        return (self.getDeviceController(type, error=False)
-                or self.createDeviceController(type))
-
-    def createDeviceController(self, type):
-        ctrl = controller.createDevController(type, self, 
recreate=self.recreate)
-        self.controllers[type] = ctrl
-        return ctrl
-
-    def createDevice(self, type, devconfig, change=False):
-        if self.recreate:
-            return
-        if type == 'vbd':
-            typedev = sxp.child_value(devconfig, 'dev')
-            if re.match('^ioemu:', typedev):
-               return;
-
-            backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
-
-            devnum = blkdev_name_to_number(sxp.child_value(devconfig, 'dev'))
-
-            backpath = "%s/backend/%s/%s/%d" % (backdom.path, type,
-                                                self.uuid, devnum)
-            frontpath = "%s/device/%s/%d" % (self.path, type, devnum)
-
-            front = { 'backend' : backpath,
-                      'backend-id' : "%i" % backdom.domid,
-                      'virtual-device' : "%i" % devnum }
-            xstransact.Write(frontpath, front)
-
-            (type, params) = string.split(sxp.child_value(devconfig,
-                                                          'uname'), ':', 1)
-            readonly = sxp.child_value(devconfig, 'mode', 'r')
-            back = { 'type' : type,
-                     'params' : params,
-                     'frontend' : frontpath,
-                     'frontend-id' : "%i" % self.domid }
-            if readonly == 'r':
-                back['read-only'] = ""  # existence indicates read-only
-            xstransact.Write(backpath, back)
-
-            return
-
-        if type == 'vif':
-            from xen.xend import XendRoot
-            xroot = XendRoot.instance()
-
-            def _get_config_ipaddr(config):
-                val = []
-                for ipaddr in sxp.children(config, elt='ip'):
-                    val.append(sxp.child0(ipaddr))
-                return val
-
-            backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
-
-            devnum = self.netif_idx
-            self.netif_idx += 1
-
-            script = sxp.child_value(devconfig, 'script',
-                                     xroot.get_vif_script())
-            script = os.path.join(xroot.network_script_dir, script)
-            bridge = sxp.child_value(devconfig, 'bridge',
-                                     xroot.get_vif_bridge())
-            mac = sxp.child_value(devconfig, 'mac')
-            ipaddr = _get_config_ipaddr(devconfig)
-
-            backpath = "%s/backend/%s/%s/%d" % (backdom.path, type,
-                                                self.uuid, devnum)
-            frontpath = "%s/device/%s/%d" % (self.path, type, devnum)
-
-            front = { 'backend' : backpath,
-                      'backend-id' : "%i" % backdom.domid,
-                      'handle' : "%i" % devnum,
-                      'mac' : mac }
-            xstransact.Write(frontpath, front)
-
-            back = { 'script' : script,
-                     'domain' : self.name,
-                     'mac' : mac,
-                     'bridge' : bridge,
-                     'frontend' : frontpath,
-                     'frontend-id' : "%i" % self.domid,
-                     'handle' : "%i" % devnum }
-            if ipaddr:
-                back['ip'] = ' '.join(ipaddr)
-            xstransact.Write(backpath, back)
-
-            return
-        
-        if type == 'vtpm':
-            backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0'))
-
-            devnum = int(sxp.child_value(devconfig, 'instance', '0'))
-            log.error("The domain has a TPM with instance %d." % devnum)
-
-            backpath = "%s/backend/%s/%s/%d" % (backdom.path, type,
-                                                self.uuid, devnum)
-            frontpath = "%s/device/%s/%d" % (self.path, type, devnum)
-
-            front = { 'backend' : backpath,
-                      'backend-id' : "%i" % backdom.domid,
-                      'handle' : "%i" % devnum }
-            xstransact.Write(frontpath, front)
-
-            back = { 'instance' : "%i" % devnum,
-                     'frontend' : frontpath,
-                     'frontend-id' : "%i" % self.domid }
-            xstransact.Write(backpath, back)
-
-            return
-
-        ctrl = self.findDeviceController(type)
-        return ctrl.createDevice(devconfig, recreate=self.recreate,
-                                 change=change)
-
-    def configureDevice(self, type, id, devconfig):
-        ctrl = self.getDeviceController(type)
-        return ctrl.configureDevice(id, devconfig)
-
-    def destroyDevice(self, type, id, change=False, reboot=False):
-        ctrl = self.getDeviceController(type)
-        return ctrl.destroyDevice(id, change=change, reboot=reboot)
-
-    def deleteDevice(self, type, id):
-        ctrl = self.getDeviceController(type)
-        return ctrl.deleteDevice(id)
-
-    def getDevice(self, type, id, error=True):
-        ctrl = self.getDeviceController(type)
-        return ctrl.getDevice(id, error=error)
-        
-    def getDeviceIds(self, type):
-        ctrl = self.getDeviceController(type)
-        return ctrl.getDeviceIds()
-    
-    def getDeviceSxprs(self, type):
-        ctrl = self.getDeviceController(type)
-        return ctrl.getDeviceSxprs()
+
+    def getDeviceController(self, name):
+        if name not in controllerClasses:
+            raise XendError("unknown device type: " + str(name))
+
+        return controllerClasses[name](self)
+
+
+    def createDevice(self, deviceClass, devconfig):
+        return self.getDeviceController(deviceClass).createDevice(devconfig)
+
+
+    def configureDevice(self, deviceClass, devid, devconfig):
+        return self.getDeviceController(deviceClass).configureDevice(
+            devid, devconfig)
+
+
+    def destroyDevice(self, deviceClass, devid):
+        return self.getDeviceController(deviceClass).destroyDevice(devid)
+
 
     def sxpr(self):
         sxpr = ['domain',
@@ -593,23 +492,8 @@
             sxpr.append(['restart_state', self.restart_state])
         if self.restart_time:
             sxpr.append(['restart_time', str(self.restart_time)])
-
-        devs = self.sxpr_devices()
-        if devs:
-            sxpr.append(devs)
         if self.config:
             sxpr.append(['config', self.config])
-        return sxpr
-
-    def sxpr_devices(self):
-        sxpr = []
-        for ty in self.controllers.keys():
-            devs = self.getDeviceSxprs(ty)
-            sxpr += devs
-        if sxpr:
-            sxpr.insert(0, 'devices')
-        else:
-            sxpr = None
         return sxpr
 
     def check_name(self, name):
@@ -753,8 +637,7 @@
         """
         self.state = STATE_VM_TERMINATED
         self.release_devices()
-        if self.store_channel:
-            self.setStoreChannel(None)
+        self.closeStoreChannel()
         if self.console_channel:
             # notify processes using this console?
             try:
@@ -785,18 +668,20 @@
     def release_devices(self):
         """Release all vm devices.
         """
-        reboot = self.restart_pending()
-        for ctrl in self.controllers.values():
-            if ctrl.isDestroyed(): continue
-            ctrl.destroyController(reboot=reboot)
+
         t = xstransact("%s/device" % self.path)
-        for d in t.list("vbd"):
-            t.remove(d)
-        for d in t.list("vif"):
-            t.remove(d)
-        for d in t.list("vtpm"):
-            t.remove(d)
+        for n in controllerClasses.keys():
+            for d in t.list(n):
+                try:
+                    t.remove(d)
+                except ex:
+                    # Log and swallow any exceptions in removal -- there's
+                    # nothing more we can do.
+                    log.exception(
+                        "Device release failed: %s; %s; %s; %s" %
+                        (self.info['name'], n, d, str(ex)))
         t.commit()
+
 
     def show(self):
         """Print virtual machine info.
@@ -853,9 +738,6 @@
                 raise VmError('invalid device')
             dev_type = sxp.name(dev_config)
 
-            if not controller.isDevControllerClass(dev_type):
-                raise VmError('unknown device type: ' + dev_type)
-            
             self.createDevice(dev_type, dev_config)
 
 
@@ -864,10 +746,7 @@
 
         @raise: VmError for invalid devices
         """
-        if self.rebooting():
-            for ctrl in self.controllers.values():
-                ctrl.initController(reboot=True)
-        else:
+        if not self.rebooting():
             self.create_configured_devices()
         self.image.createDeviceModel()
 
@@ -877,47 +756,19 @@
         @param dev_config: device configuration
         """
         dev_type = sxp.name(dev_config)
-        dev = self.createDevice(dev_type, dev_config, change=True)
-        self.config.append(['device', dev.getConfig()])
-        return dev.sxpr()
-
-    def device_configure(self, dev_config, id):
+        devid = self.createDevice(dev_type, dev_config)
+#        self.config.append(['device', dev.getConfig()])
+        return self.getDeviceController(dev_type).sxpr(devid)
+
+
+    def device_configure(self, dev_config, devid):
         """Configure an existing device.
-
         @param dev_config: device configuration
-        @param id:         device id
-        """
-        type = sxp.name(dev_config)
-        dev = self.getDevice(type, id)
-        old_config = dev.getConfig()
-        new_config = dev.configure(dev_config, change=True)
-        # Patch new config into vm config.
-        new_full_config = ['device', new_config]
-        old_full_config = ['device', old_config]
-        old_index = self.config.index(old_full_config)
-        self.config[old_index] = new_full_config
-        return new_config
-
-    def device_refresh(self, type, id):
-        """Refresh a device.
-
-        @param type: device type
-        @param id:   device id
-        """
-        dev = self.getDevice(type, id)
-        dev.refresh()
-        
-    def device_delete(self, type, id):
-        """Destroy and remove a device.
-
-        @param type: device type
-        @param id:   device id
-        """
-        dev = self.getDevice(type, id)
-        dev_config = dev.getConfig()
-        if dev_config:
-            self.config.remove(['device', dev_config])
-        self.deleteDevice(type, dev.getId())
+        @param devid:      device id
+        """
+        deviceClass = sxp.name(dev_config)
+        self.configureDevice(deviceClass, devid, dev_config)
+
 
     def configure_restart(self):
         """Configure the vm restart mode.
@@ -1036,7 +887,7 @@
         """Configure a vm.
 
         """
-        self.configure_fields()
+        self.configure_maxmem()
         self.create_devices()
         self.create_blkif()
 
@@ -1047,26 +898,15 @@
 
         """
         return
-        blkif = self.getDeviceController("vbd", error=False)
-        if not blkif:
-            blkif = self.createDeviceController("vbd")
-            backend = blkif.getBackend(0)
-            backend.connect(recreate=self.recreate)
-
-    def configure_fields(self):
-        """Process the vm configuration fields using the registered handlers.
-        """
-        index = {}
-        for field in sxp.children(self.config):
-            field_name = sxp.name(field)
-            field_index = index.get(field_name, 0)
-            field_handler = config_handlers.get(field_name)
-            # Ignore unknown fields. Warn?
-            if field_handler:
-                v = field_handler(self, self.config, field, field_index)
-            else:
-                log.warning("Unknown config field %s", field_name)
-            index[field_name] = field_index + 1
+
+    def configure_maxmem(self):
+        try:
+            maxmem = int(sxp.child_value(self.config, 'maxmem', self.memory))
+            xc.domain_setmaxmem(self.domid, maxmem_kb = maxmem * 1024)
+        except:
+            raise VmError("invalid maxmem: " +
+                          sxp.child_value(self.config, 'maxmem'))
+
 
     def vcpu_hotplug(self, vcpu, state):
         """Disable or enable VCPU in domain.
@@ -1138,26 +978,6 @@
                 self.vcpu_hotplug(vcpu, 0)
 
 
-def vm_field_ignore(_, _1, _2, _3):
-    """Dummy config field handler used for fields with built-in handling.
-    Matches the signature required by config_handlers.
-    """
-    pass
-
-
-def vm_field_maxmem(vm, _1, val, _2):
-    """Config field handler to configure vm memory limit.  Matches the
-    signature required by config_handlers.
-    """
-    maxmem = sxp.child0(val)
-    if maxmem is None:
-        maxmem = vm.memory
-    try:
-        maxmem = int(maxmem)
-    except:
-        raise VmError("invalid maxmem: " + str(maxmem))
-    xc.domain_setmaxmem(vm.domid, maxmem_kb = maxmem * 1024)
-
 
 #============================================================================
 # Register image handlers.
@@ -1172,37 +992,24 @@
 addImageHandlerClass(VmxImageHandler)
 
 
-"""Table of handlers for field configuration.
-
-field_name[String]: fn(vm, config, field, index) -> value(ignored)
-"""
-config_handlers = {
-    
-    # Ignore the fields we already handle.
-    
-    'name':       vm_field_ignore,
-    'memory':     vm_field_ignore,
-    'ssidref':    vm_field_ignore,
-    'cpu':        vm_field_ignore,
-    'cpu_weight': vm_field_ignore,
-    'restart':    vm_field_ignore,
-    'image':      vm_field_ignore,
-    'device':     vm_field_ignore,
-    'backend':    vm_field_ignore,
-    'vcpus':      vm_field_ignore,
-    'bootloader': vm_field_ignore,
-    
-    # Register other config handlers.
-    'maxmem':     vm_field_maxmem
-    }
-
-
 #============================================================================
 # Register device controllers and their device config types.
 
+"""A map from device-class names to the subclass of DevController that
+implements the device control specific to that device-class."""
+controllerClasses = {}
+
+
+def addControllerClass(device_class, cls):
+    """Register a subclass of DevController to handle the named device-class.
+    """
+    cls.deviceClass = device_class
+    controllerClasses[device_class] = cls
+
+
 from xen.xend.server import blkif, netif, tpmif, pciif, usbif
-controller.addDevControllerClass("vbd",  blkif.BlkifController)
-controller.addDevControllerClass("vif",  netif.NetifController)
-controller.addDevControllerClass("vtpm", tpmif.TPMifController)
-controller.addDevControllerClass("pci",  pciif.PciController)
-controller.addDevControllerClass("usb",  usbif.UsbifController)
+addControllerClass('vbd',  blkif.BlkifController)
+addControllerClass('vif',  netif.NetifController)
+addControllerClass('vtpm', tpmif.TPMifController)
+addControllerClass('pci',  pciif.PciController)
+addControllerClass('usb',  usbif.UsbifController)
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/image.py    Mon Sep 19 10:51:05 2005
@@ -18,7 +18,7 @@
 import os, string
 import re
 
-import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
+import xen.lowlevel.xc
 from xen.xend import sxp
 from xen.xend.XendError import VmError
 from xen.xend.XendLogging import log
@@ -26,6 +26,10 @@
 from xen.xend.xenstore.xstransact import xstransact
 
 from xen.xend.server import channel
+
+
+xc = xen.lowlevel.xc.new()
+
 
 MAX_GUEST_CMDLINE = 1024
 
@@ -155,7 +159,8 @@
                 self.unlink(self.kernel)
                 self.unlink(self.ramdisk)
             if dom <= 0:
-                raise VmError('Creating domain failed: name=%s' % self.vm.name)
+                raise VmError('Creating domain failed: name=%s' %
+                              self.vm.getName())
         log.debug("initDomain: cpu=%d mem_kb=%d ssidref=%d dom=%d", cpu, 
mem_kb, ssidref, dom)
         xc.domain_setcpuweight(dom, cpu_weight)
         xc.domain_setmaxmem(dom, mem_kb)
@@ -183,21 +188,22 @@
             return
 
         # Set params and call buildDomain().
-        self.flags = self.vm.backend_flags
+        self.flags = self.vm.getBackendFlags()
 
         if not os.path.isfile(self.kernel):
             raise VmError('Kernel image does not exist: %s' % self.kernel)
         if self.ramdisk and not os.path.isfile(self.ramdisk):
             raise VmError('Kernel ramdisk does not exist: %s' % self.ramdisk)
         if len(self.cmdline) >= MAX_GUEST_CMDLINE:
-            log.warning('kernel cmdline too long, domain %d', self.vm.domid)
+            log.warning('kernel cmdline too long, domain %d',
+                        self.vm.getDomain())
         
         log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype,
-                 self.vm.domid, self.vm.vcpus)
+                 self.vm.getDomain(), self.vm.getVCpuCount())
         err = self.buildDomain()
         if err != 0:
             raise VmError('Building domain failed: ostype=%s dom=%d err=%d'
-                          % (self.ostype, self.vm.domid, err))
+                          % (self.ostype, self.vm.getDomain(), err))
 
     def getDomainMemory(self, mem_mb):
         """Memory (in KB) the domain will need for mem_mb (in MB)."""
@@ -237,23 +243,23 @@
         else:
             console_evtchn = 0
 
-        log.debug("dom            = %d", self.vm.domid)
+        log.debug("dom            = %d", self.vm.getDomain())
         log.debug("image          = %s", self.kernel)
         log.debug("store_evtchn   = %d", store_evtchn)
         log.debug("console_evtchn = %d", console_evtchn)
         log.debug("cmdline        = %s", self.cmdline)
         log.debug("ramdisk        = %s", self.ramdisk)
         log.debug("flags          = %d", self.flags)
-        log.debug("vcpus          = %d", self.vm.vcpus)
-
-        ret = xc.linux_build(dom            = self.vm.domid,
+        log.debug("vcpus          = %d", self.vm.getVCpuCount())
+
+        ret = xc.linux_build(dom            = self.vm.getDomain(),
                              image          = self.kernel,
                              store_evtchn   = store_evtchn,
                              console_evtchn = console_evtchn,
                              cmdline        = self.cmdline,
                              ramdisk        = self.ramdisk,
                              flags          = self.flags,
-                             vcpus          = self.vm.vcpus)
+                             vcpus          = self.vm.getVCpuCount())
         if isinstance(ret, dict):
             self.set_vminfo(ret)
             return 0
@@ -297,22 +303,22 @@
 
     def buildDomain(self):
         # Create an event channel
-        self.device_channel = channel.eventChannel(0, self.vm.domid)
+        self.device_channel = channel.eventChannel(0, self.vm.getDomain())
         log.info("VMX device model port: %d", self.device_channel.port2)
         if self.vm.store_channel:
             store_evtchn = self.vm.store_channel.port2
         else:
             store_evtchn = 0
-        ret = xc.vmx_build(dom            = self.vm.domid,
+        ret = xc.vmx_build(dom            = self.vm.getDomain(),
                            image          = self.kernel,
                            control_evtchn = self.device_channel.port2,
                            store_evtchn   = store_evtchn,
-                           memsize        = self.vm.memory,
+                           memsize        = self.vm.getMemoryTarget(),
                            memmap         = self.memmap_value,
                            cmdline        = self.cmdline,
                            ramdisk        = self.ramdisk,
                            flags          = self.flags,
-                           vcpus          = self.vm.vcpus)
+                           vcpus          = self.vm.getVCpuCount())
         if isinstance(ret, dict):
             self.set_vminfo(ret)
             return 0
@@ -391,7 +397,7 @@
         elif vnc:
             ret = ret + ['-vnc', '-k', 'en-us']
         if vnc:
-            vncport = int(self.vm.domid) + 5900
+            vncport = int(self.vm.getDomain()) + 5900
             ret = ret + ['-vncport', '%d' % vncport]
         return ret
 
@@ -405,9 +411,9 @@
         vnc = self.vncParams()
         if len(vnc):
             args = args + vnc
-        args = args + ([ "-d",  "%d" % self.vm.domid,
+        args = args + ([ "-d",  "%d" % self.vm.getDomain(),
                   "-p", "%d" % self.device_channel.port1,
-                  "-m", "%s" % self.vm.memory ])
+                  "-m", "%s" % self.vm.getMemoryTarget() ])
         args = args + self.dmargs
         env = dict(os.environ)
         env['DISPLAY'] = self.display
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/scheduler.py
--- a/tools/python/xen/xend/scheduler.py        Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/scheduler.py        Mon Sep 19 10:51:05 2005
@@ -13,11 +13,12 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
 
 import threading
 
-def later(delay, fn, args=(), kwargs={}):
+def later(delay, fn, *args, **kwargs):
     """Schedule a function to be called later.
 
     @param delay:  delay in seconds
@@ -29,7 +30,7 @@
     timer.start()
     return timer
 
-def now(fn, args=(), kwargs={}):
+def now(fn, *args, **kwargs):
     """Schedule a function to be called now.
 
     @param fn:     function
diff -r cedb89d6b707 -r 308260e5868c 
tools/python/xen/xend/server/SrvDomainDir.py
--- a/tools/python/xen/xend/server/SrvDomainDir.py      Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/SrvDomainDir.py      Mon Sep 19 10:51:05 2005
@@ -85,7 +85,7 @@
     def _op_create_cb(self, dominfo, configstring, req):
         """Callback to handle domain creation.
         """
-        dom = dominfo.name
+        dom = dominfo.getName()
         domurl = "%s/%s" % (req.prePathURL(), dom)
         req.setResponseCode(http.CREATED, "created")
         req.setHeader("Location", domurl)
@@ -112,7 +112,7 @@
         fn = FormFn(self.xd.domain_restore,
                     [['file', 'str']])
         dominfo = fn(req.args)
-        dom = dominfo.name
+        dom = dominfo.getName()
         domurl = "%s/%s" % (req.prePathURL(), dom)
         req.setResponseCode(http.CREATED)
         req.setHeader("Location", domurl)
@@ -152,12 +152,12 @@
             domains = self.xd.list_sorted()
             req.write('<ul>')
             for d in domains:
-               req.write('<li><a href="%s%s"> Domain %s</a>'
-                         % (url, d.name, d.name))
-               req.write('id=%s' % d.domid)
-               req.write('memory=%d'% d.memory)
-               req.write('ssidref=%d'% d.ssidref)
-               req.write('</li>')
+                req.write('<li><a href="%s%s"> Domain %s</a>'
+                          % (url, d.getName(), d.getName()))
+                req.write('id=%s' % d.getDomain())
+                req.write('memory=%d'% d.getMemoryTarget())
+                req.write('ssidref=%d'% d.getSsidref())
+                req.write('</li>')
             req.write('</ul>')
 
     def form(self, req):
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/SrvNode.py
--- a/tools/python/xen/xend/server/SrvNode.py   Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/SrvNode.py   Mon Sep 19 10:51:05 2005
@@ -15,7 +15,6 @@
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
 #============================================================================
 
-import os
 
 from xen.web.SrvDir import SrvDir
 from xen.xend import sxp
@@ -32,15 +31,15 @@
         self.add('dmesg', 'SrvDmesg')
         self.add('log', 'SrvXendLog')
 
-    def op_shutdown(self, op, req):
+    def op_shutdown(self, _1, _2):
         val = self.xn.shutdown()
         return val
 
-    def op_reboot(self, op, req):
+    def op_reboot(self, _1, _2):
         val = self.xn.reboot()
         return val
 
-    def op_cpu_bvt_slice_set(self, op, req):
+    def op_cpu_bvt_slice_set(self, _, req):
         fn = FormFn(self.xn.cpu_bvt_slice_set,
                     [['ctx_allow', 'int']])
         val = fn(req.args, {})
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/SrvServer.py
--- a/tools/python/xen/xend/server/SrvServer.py Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/SrvServer.py Mon Sep 19 10:51:05 2005
@@ -44,13 +44,17 @@
 
 from xen.web.httpserver import HttpServer, UnixHttpServer
 
-from xen.xend import XendRoot; xroot = XendRoot.instance()
+from xen.xend import XendRoot
 from xen.xend import Vifctl
 from xen.xend.XendLogging import log
 from xen.web.SrvDir import SrvDir
 import time
 
 from SrvRoot import SrvRoot
+
+
+xroot = XendRoot.instance()
+
 
 class XendServers:
 
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/blkif.py
--- a/tools/python/xen/xend/server/blkif.py     Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/blkif.py     Mon Sep 19 10:51:05 2005
@@ -13,322 +13,47 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
 
-"""Support for virtual block devices.
-"""
+
+import re
 import string
 
 from xen.util import blkif
-from xen.xend.XendError import XendError, VmError
-from xen.xend.XendRoot import get_component
-from xen.xend.XendLogging import log
 from xen.xend import sxp
-from xen.xend import Blkctl
-from xen.xend.xenstore import DBVar
 
-from xen.xend.server.controller import Dev, DevController
+from xen.xend.server.DevController import DevController
 
-class BlkifBackend:
-    """ Handler for the 'back-end' channel to a block device driver domain
-    on behalf of a front-end domain.
-    Must be connected using connect() before it can be used.
-    """
 
-    def __init__(self, controller, id, dom, recreate=False):
-        self.controller = controller
-        self.id = id
-        self.frontendDomain = self.controller.getDomain()
-        self.backendDomain = dom
-        self.destroyed = False
-        self.connected = False
-        self.status = None
-
-    def init(self, recreate=False, reboot=False):
-        self.destroyed = False
-        self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED
-        self.frontendDomain = self.controller.getDomain()
-
-    def __str__(self):
-        return ('<BlkifBackend frontend=%d backend=%d id=%d>'
-                % (self.frontendDomain,
-                   self.backendDomain,
-                   self.id))
-
-    def getId(self):
-        return self.id
-
-    def connect(self, recreate=False):
-        """Connect to the blkif control interface.
-
-        @param recreate: true if after xend restart
-        """
-        log.debug("Connecting blkif %s", str(self))
-        if recreate or self.connected:
-            self.connected = True
-            pass
-        
-    def destroy(self, change=False, reboot=False):
-        """Disconnect from the blkif control interface and destroy it.
-        """
-        self.destroyed = True
-        # For change true need to notify front-end, or back-end will do it?
-
-    def connectInterface(self, val):
-        self.status = BLKIF_INTERFACE_STATUS_CONNECTED
-            
-    def interfaceDisconnected(self):
-        self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED
-        
-class BlkDev(Dev):
-    """Info record for a block device.
-    """
-
-    __exports__ = Dev.__exports__ + [
-        DBVar('dev',          ty='str'),
-        DBVar('vdev',         ty='int'),
-        DBVar('mode',         ty='str'),
-        DBVar('viftype',      ty='str'),
-        DBVar('params',       ty='str'),
-        DBVar('node',         ty='str'),
-        DBVar('device',       ty='long'),
-        DBVar('dev_handle',   ty='long'),
-        DBVar('start_sector', ty='long'),
-        DBVar('nr_sectors',   ty='long'),
-        ]
-
-    def __init__(self, controller, id, config, recreate=False):
-        Dev.__init__(self, controller, id, config, recreate=recreate)
-        self.dev = None
-        self.uname = None
-        self.vdev = None
-        self.mode = None
-        self.type = None
-        self.params = None
-        self.node = None
-        self.device = None
-        self.dev_handle = 0
-        self.start_sector = None
-        self.nr_sectors = None
-        
-        self.frontendDomain = self.getDomain()
-        self.backendDomain = None
-        self.backendId = 0
-        self.configure(self.config, recreate=recreate)
-
-    def exportToDB(self, save=False):
-        Dev.exportToDB(self, save=save)
-        backend = self.getBackend()
-
-    def init(self, recreate=False, reboot=False):
-        self.frontendDomain = self.getDomain()
-        backend = self.getBackend()
-        self.backendId = backend.domid
-
-    def configure(self, config, change=False, recreate=False):
-        if change:
-            raise XendError("cannot reconfigure vbd")
-        self.config = config
-        self.uname = sxp.child_value(config, 'uname')
-        if not self.uname:
-            raise VmError('vbd: Missing uname')
-        # Split into type and type-specific params (which are passed to the
-        # type-specific control script).
-        (self.type, self.params) = string.split(self.uname, ':', 1)
-        self.dev = sxp.child_value(config, 'dev')
-        if not self.dev:
-            raise VmError('vbd: Missing dev')
-        self.mode = sxp.child_value(config, 'mode', 'r')
-        
-        self.vdev = blkif.blkdev_name_to_number(self.dev)
-        if not self.vdev:
-            raise VmError('vbd: Device not found: %s' % self.dev)
-        
-        try:
-            xd = get_component('xen.xend.XendDomain')
-            self.backendDomain = 
xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).domid
-        except:
-            raise XendError('invalid backend domain')
-
-        return self.config
-
-    def attach(self, recreate=False, change=False):
-        if recreate:
-            pass
-        else:
-            node = Blkctl.block('bind', self.type, self.params)
-            self.setNode(node)
-            self.attachBackend()
-        if change:
-            self.interfaceChanged()
-
-    def unbind(self):
-        if self.node is None: return
-        log.debug("Unbinding vbd (type %s) from %s"
-                  % (self.type, self.node))
-        Blkctl.block('unbind', self.type, self.node)
-
-    def setNode(self, node):
-    
-        # NOTE: 
-        # This clause is testing code for storage system experiments.
-        # Add a new disk type that will just pass an opaque id in the
-        # dev_handle and use an experimental device type.
-        # Please contact andrew.warfield@xxxxxxxxxxxx with any concerns.
-        if self.type == 'parallax':
-            self.node   = node
-            self.device =  61440 # (240,0)
-            self.dev_handle = long(self.params)
-            self.nr_sectors = long(0)
-            return
-        # done.
-            
-        mounted_mode = self.check_mounted(node)
-        if not '!' in self.mode and mounted_mode:
-            if mounted_mode == "w":
-                raise VmError("vbd: Segment %s is in writable use" %
-                              self.uname)
-            elif 'w' in self.mode:
-                raise VmError("vbd: Segment %s is in read-only use" %
-                              self.uname)
-            
-        segment = blkif.blkdev_segment(node)
-        if not segment:
-            raise VmError("vbd: Segment not found: uname=%s" % self.uname)
-        self.node = node
-        self.device = segment['device']
-        self.start_sector = segment['start_sector']
-        self.nr_sectors = segment['nr_sectors']
-
-    def check_mounted(self, name):
-        mode = blkif.mount_mode(name)
-        xd = get_component('xen.xend.XendDomain')
-        for vm in xd.list():
-            ctrl = vm.getDeviceController(self.getType(), error=False)
-            if (not ctrl): continue
-            for dev in ctrl.getDevices():
-                if dev is self: continue
-                if dev.type == 'phy' and name == 
blkif.expand_dev_name(dev.params):
-                    mode = dev.mode
-                    if 'w' in mode:
-                        return 'w'
-        if mode and 'r' in mode:
-            return 'r'
-        return None
-
-    def readonly(self):
-        return 'w' not in self.mode
-
-    def sxpr(self):
-        val = ['vbd',
-               ['id', self.id],
-               ['vdev', self.vdev],
-               ['device', self.device],
-               ['mode', self.mode]]
-        if self.dev:
-            val.append(['dev', self.dev])
-        if self.uname:
-            val.append(['uname', self.uname])
-        if self.node:
-            val.append(['node', self.node])
-        return val
-
-    def getBackend(self):
-        return self.controller.getBackend(self.backendDomain)
-
-    def refresh(self):
-        log.debug("Refreshing vbd domain=%d id=%s", self.frontendDomain,
-                  self.id)
-        self.interfaceChanged()
-
-    def destroy(self, change=False, reboot=False):
-        """Destroy the device. If 'change' is true notify the front-end 
interface.
-
-        @param change: change flag
-        """
-        self.destroyed = True
-        log.debug("Destroying vbd domain=%d id=%s", self.frontendDomain,
-                  self.id)
-        if change:
-            self.interfaceChanged()
-        self.unbind()
-
-    def interfaceChanged(self):
-        """Tell the back-end to notify the front-end that a device has been
-        added or removed.
-        """
-        self.getBackend().interfaceChanged()
-
-    def attachBackend(self):
-        """Attach the device to its controller.
-
-        """
-        self.getBackend().connect()
-        
 class BlkifController(DevController):
     """Block device interface controller. Handles all block devices
     for a domain.
     """
     
-    def __init__(self, vm, recreate=False):
+    def __init__(self, vm):
         """Create a block device controller.
         """
-        DevController.__init__(self, vm, recreate=recreate)
-        self.backends = {}
-        self.backendId = 0
+        DevController.__init__(self, vm)
 
-    def initController(self, recreate=False, reboot=False):
-        self.destroyed = False
-        if reboot:
-            self.rebootBackends()
-            self.rebootDevices()
 
-    def sxpr(self):
-        val = ['blkif', ['dom', self.getDomain()]]
-        return val
+    def getDeviceDetails(self, config):
+        """@see DevController.getDeviceDetails"""
+        
+        typedev = sxp.child_value(config, 'dev')
+        if re.match('^ioemu:', typedev):
+            return
 
-    def rebootBackends(self):
-        for backend in self.backends.values():
-            backend.init(reboot=True)
+        devid = blkif.blkdev_name_to_number(sxp.child_value(config, 'dev'))
 
-    def getBackendById(self, id):
-        return self.backends.get(id)
+        (typ, params) = string.split(sxp.child_value(config, 'uname'), ':', 1)
+        back = { 'type' : typ,
+                 'params' : params
+                 }
 
-    def getBackendByDomain(self, dom):
-        for backend in self.backends.values():
-            if backend.backendDomain == dom:
-                return backend
-        return None
+        if 'r' == sxp.child_value(config, 'mode', 'r'):
+            back['read-only'] = ""  # existence indicates read-only
 
-    def getBackend(self, dom):
-        backend = self.getBackendByDomain(dom)
-        if backend: return backend
-        backend = BlkifBackend(self, self.backendId, dom)
-        self.backendId += 1
-        self.backends[backend.getId()] = backend
-        backend.init()
-        return backend
+        front = { 'virtual-device' : "%i" % devid }
 
-    def newDevice(self, id, config, recreate=False):
-        """Create a device..
-
-        @param id:      device id
-        @param config:   device configuration
-        @param recreate: if true it's being recreated (after xend restart)
-        @type  recreate: bool
-        @return: device
-        @rtype:  BlkDev
-        """
-        return BlkDev(self, id, config, recreate=recreate)
-        
-    def destroyController(self, reboot=False):
-        """Destroy the controller and all devices.
-        """
-        self.destroyed = True
-        log.debug("Destroying blkif domain=%d", self.getDomain())
-        self.destroyDevices(reboot=reboot)
-        self.destroyBackends(reboot=reboot)
-
-    def destroyBackends(self, reboot=False):
-        for backend in self.backends.values():
-            backend.destroy(reboot=reboot)
+        return (devid, back, front)
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/channel.py
--- a/tools/python/xen/xend/server/channel.py   Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/channel.py   Mon Sep 19 10:51:05 2005
@@ -43,33 +43,6 @@
 
     interdomain = classmethod(interdomain)
 
-    def restoreFromDB(cls, db, dom1, dom2, port1=0, port2=0):
-        """Create an event channel using db info if available.
-        Inverse to saveToDB().
-
-        @param db db
-        @param dom1
-        @param dom2
-        @param port1
-        @param port2
-        """
-        try:
-            dom1  = int(db['dom1'].getData())
-        except: pass
-        try:
-            dom2  = int(db['dom2'].getData())
-        except: pass
-        try:
-            port1 = int(db['port1'].getData())
-        except: pass
-        try:
-            port2 = int(db['port2'].getData())
-        except: pass
-        evtchn = cls.interdomain(dom1, dom2, port1=port1, port2=port2)
-        return evtchn
-
-    restoreFromDB = classmethod(restoreFromDB)
-
     def __init__(self, dom1, dom2, d):
         d['dom1'] = dom1
         d['dom2'] = dom2
@@ -92,18 +65,6 @@
             print 'EventChannel>close>', self
         evtchn_close(self.dom1, self.port1)
         evtchn_close(self.dom2, self.port2)
-
-    def saveToDB(self, db, save=False):
-        """Save the event channel to the db so it can be restored later,
-        using restoreFromDB() on the class.
-
-        @param db db
-        """
-        db['dom1']  = str(self.dom1)
-        db['dom2']  = str(self.dom2)
-        db['port1'] = str(self.port1)
-        db['port2'] = str(self.port2)
-        db.saveDB(save=save)
 
     def sxpr(self):
         return ['event-channel',
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/netif.py
--- a/tools/python/xen/xend/server/netif.py     Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/netif.py     Mon Sep 19 10:51:05 2005
@@ -13,396 +13,64 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
+
 
 """Support for virtual network interfaces.
 """
 
-import random
-
-from xen.util.mac import macFromString, macToString
+import os
 
 from xen.xend import sxp
-from xen.xend import Vifctl
-from xen.xend.XendError import XendError, VmError
-from xen.xend.XendLogging import log
-from xen.xend import XendVnet
-from xen.xend.XendRoot import get_component
-from xen.xend.xenstore import DBVar
 
-from xen.xend.server.controller import Dev, DevController
+from xen.xend.server.DevController import DevController
 
-class NetDev(Dev):
-    """A network device.
-    """
 
-    # State:
-    # inherited + 
-    # ./config
-    # ./mac
-    # ./be_mac
-    # ./bridge
-    # ./script
-    # ./ipaddr ?
-    #
-    # ./credit
-    # ./period
-    #
-    # ./vifctl: up/down?
-    # ./vifname
-    #
-    #
-    # Poss should have no backend state here - except for ref to backend's own 
tree
-    # for the device? And a status - the one we want.
-    # ./back/dom
-    # ./back/devid - id for back-end (netif_handle) - same as front/devid
-    # ./back/id    - backend id (if more than one b/e per domain)
-    # ./back/status
-    # ./back/tx_shmem_frame  - actually these belong in back-end state
-    # ./back/rx_shmem_frame
-    #
-    # ./front/dom
-    # ./front/devid
-    # ./front/status - need 2: one for requested, one for actual? Or drive 
from dev status
-    # and this is front status only.
-    # ./front/tx_shmem_frame
-    # ./front/rx_shmem_frame
-    #
-    # ./evtchn/front - here or in front/back?
-    # ./evtchn/back
-    # ./evtchn/status ?
-    # At present created by dev: but should be created unbound by front/back
-    # separately and then bound (by back)?
+next_devid = 1
 
-    __exports__ = Dev.__exports__ + [
-        DBVar('config',  ty='sxpr'),
-        DBVar('mac',     ty='mac'),
-        DBVar('be_mac',  ty='mac'),
-        DBVar('bridge',  ty='str'),
-        DBVar('script',  ty='str'),
-        DBVar('credit',  ty='int'),
-        DBVar('period',  ty='int'),
-        DBVar('vifname', ty='str'),
-        ]
 
-    def __init__(self, controller, id, config, recreate=False):
-        Dev.__init__(self, controller, id, config, recreate=recreate)
-        self.vif = int(self.id)
-        self.status = None
-        self.frontendDomain = self.getDomain()
-        self.backendDomain = None
-        self.credit = None
-        self.period = None
-        self.mac = None
-        self.be_mac = None
-        self.bridge = None
-        self.script = None
-        self.ipaddr = None
-        self.mtu = None
-        self.vifname = None
-        self.configure(self.config, recreate=recreate)
-
-    def exportToDB(self, save=False):
-        Dev.exportToDB(self, save=save)
-
-    def init(self, recreate=False, reboot=False):
-        self.destroyed = False
-        self.status = NETIF_INTERFACE_STATUS_DISCONNECTED
-        self.frontendDomain = self.getDomain()
-
-    def _get_config_mac(self, config):
-        vmac = sxp.child_value(config, 'mac')
-        if not vmac: return None
-        try:
-            mac = macFromString(vmac)
-        except:
-            raise XendError("invalid mac: %s" % vmac)
-        return mac
-
-    def _get_config_be_mac(self, config):
-        vmac = sxp.child_value(config, 'be_mac')
-        if not vmac: return None
-        try:
-            mac = macFromString(vmac)
-        except:
-            raise XendError("invalid backend mac: %s" % vmac)
-        return mac
-
-    def _get_config_ipaddr(self, config):
-        ips = sxp.children(config, elt='ip')
-        if ips:
-            val = []
-            for ipaddr in ips:
-                val.append(sxp.child0(ipaddr))
-        else:
-            val = None
-        return val
-
-    def _get_config_mtu(self, config):
-        mtu = sxp.child_value(config, 'mtu')
-        if not mtu: return None
-        try:
-            mtu = int(mtu)
-        except:
-            raise XendError("invalid mtu: %s" & mtu)
-        return mtu
-
-    def configure(self, config, change=False, recreate=False):
-        if change:
-            return self.reconfigure(config)
-        self.config = config
-        self.mac = None
-        self.be_mac = None
-        self.bridge = None
-        self.script = None
-        self.ipaddr = []
-        self.vifname = None
-
-        self.vifname = sxp.child_value(config, 'vifname')
-        if self.vifname is None:
-            self.vifname = self.default_vifname()
-        if len(self.vifname) > 15:
-            raise XendError('invalid vifname: too long: ' + self.vifname)
-        mac = self._get_config_mac(config)
-        if mac is None:
-            raise XendError("invalid mac")
-        self.mac = mac
-        self.be_mac = self._get_config_be_mac(config)
-        self.bridge = sxp.child_value(config, 'bridge')
-        self.script = sxp.child_value(config, 'script')
-        self.ipaddr = self._get_config_ipaddr(config) or []
-        self.mtu = self._get_config_mtu(config)
-        self._config_credit_limit(config)
-        
-        try:
-            if recreate:
-                self.backendDomain = int(sxp.child_value(config, 'backend', 
'0'))
-            else:
-                #todo: Code below will fail on xend restart when backend is 
not domain 0.
-                xd = get_component('xen.xend.XendDomain')
-                self.backendDomain = 
xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).domid
-        except:
-            raise XendError('invalid backend domain')
-        return self.config
-
-    def reconfigure(self, config):
-        """Reconfigure the interface with new values.
-        Not all configuration parameters can be changed:
-        bridge, script and ip addresses can,
-        backend and mac cannot.
-
-        To leave a parameter unchanged, omit it from the changes.
-
-        @param config configuration changes
-        @return updated interface configuration
-        @raise XendError on errors
-        """
-        changes = {}
-        mac = self._get_config_mac(config)
-        be_mac = self._get_config_be_mac(config)
-        bridge = sxp.child_value(config, 'bridge')
-        script = sxp.child_value(config, 'script')
-        ipaddr = self._get_config_ipaddr(config)
-        mtu = self._get_config_mtu(config)
-        
-        xd = get_component('xen.xend.XendDomain')
-        backendDomain = xd.domain_lookup_by_name(sxp.child_value(config, 
'backend', '0')).domid
-
-        if (mac is not None) and (mac != self.mac):
-            raise XendError("cannot change mac")
-        if (be_mac is not None) and (be_mac != self.be_mac):
-            raise XendError("cannot change backend mac")
-        if (backendDomain is not None) and (backendDomain != 
self.backendDomain):
-            raise XendError("cannot change backend")
-        if (bridge is not None) and (bridge != self.bridge):
-            changes['bridge'] = bridge
-        if (script is not None) and (script != self.script):
-            changes['script'] = script
-        if (ipaddr is not None) and (ipaddr != self.ipaddr):
-            changes['ipaddr'] = ipaddr
-        if (mtu is not None) and (mtu != self.mtu):
-            changes['mtu'] = mtu
-
-        if changes:
-            self.vifctl("down")
-            for (k, v) in changes.items():
-                setattr(self, k, v)
-            self.config = sxp.merge(config, self.config)
-            self.vifctl("up")
-
-        self._config_credit_limit(config, change=True)
-        return self.config
-
-    def _config_credit_limit(self, config, change=False):
-        period = sxp.child_value(config, 'period')
-        credit = sxp.child_value(config, 'credit')
-        if period and credit:
-            try:
-                period = int(period)
-                credit = int(credit)
-            except ex:
-                raise XendError('vif: invalid credit limit')
-            if change:
-                self.setCreditLimit(credit, period)
-                self.config = sxp.merge([sxp.name(self.config),
-                                         ['credit', credit],
-                                         ['period', period]],
-                                        self.config)
-            else:
-                self.period = period
-                self.credit = credit
-        elif period or credit:
-            raise XendError('vif: invalid credit limit')
-
-    def sxpr(self):
-        vif = str(self.vif)
-        mac = self.get_mac()
-        val = ['vif',
-               ['id', self.id],
-               ['vif', vif],
-               ['mac', mac],
-               ['vifname', self.vifname],
-               ]
-
-        if self.be_mac:
-            val.append(['be_mac', self.get_be_mac()])
-        if self.bridge:
-            val.append(['bridge', self.bridge])
-        if self.script:
-            val.append(['script', self.script])
-        for ip in self.ipaddr:
-            val.append(['ip', ip])
-        if self.credit:
-            val.append(['credit', self.credit])
-        if self.period:
-            val.append(['period', self.period])
-        return val
-
-    def get_vifname(self):
-        """Get the virtual interface device name.
-        """
-        return self.vifname
-
-    def default_vifname(self):
-        return "vif%d.%d" % (self.frontendDomain, self.vif)
-    
-    def get_mac(self):
-        """Get the MAC address as a string.
-        """
-        return macToString(self.mac)
-
-    def get_be_mac(self):
-        """Get the backend MAC address as a string.
-        """
-        return macToString(self.be_mac)
-
-    def vifctl_params(self, vmname=None):
-        """Get the parameters to pass to vifctl.
-        """
-        dom = self.frontendDomain
-        if vmname is None:
-            xd = get_component('xen.xend.XendDomain')
-            try:
-                vm = xd.domain_lookup(dom)
-                vmname = vm.name
-            except:
-                vmname = 'Domain-%d' % dom
-        return { 'domain': vmname,
-                 'vif'   : self.get_vifname(), 
-                 'mac'   : self.get_mac(),
-                 'bridge': self.bridge,
-                 'script': self.script,
-                 'ipaddr': self.ipaddr, }
-
-    def vifctl(self, op, vmname=None):
-        """Bring the device up or down.
-        The vmname is needed when bringing a device up for a new domain because
-        the domain is not yet in the table so we can't look its name up.
-
-        @param op: operation name (up, down)
-        @param vmname: vmname
-        """
-        if op == 'up':
-            Vifctl.set_vif_name(self.default_vifname(), self.vifname)
-        Vifctl.vifctl(op, **self.vifctl_params(vmname=vmname))
-        vnet = XendVnet.instance().vnet_of_bridge(self.bridge)
-        if vnet:
-            vnet.vifctl(op, self.get_vifname(), self.get_mac())
-
-    def attach(self, recreate=False, change=False):
-        if recreate:
-            pass
-        else:
-            if self.credit and self.period:
-                #self.send_be_creditlimit(self.credit, self.period)
-                pass
-            self.vifctl('up', vmname=self.getDomainName())
-        
-    def destroy(self, change=False, reboot=False):
-        """Destroy the device's resources and disconnect from the back-end
-        device controller. If 'change' is true notify the front-end interface.
-
-        @param change: change flag
-        """
-        self.destroyed = True
-        self.status = NETIF_INTERFACE_STATUS_CLOSED
-        log.debug("Destroying vif domain=%d vif=%d", self.frontendDomain, 
self.vif)
-        self.vifctl('down')
-        if change:
-            self.reportStatus()
-
-    def setCreditLimit(self, credit, period):
-        #todo: these params should be in sxpr and vif config.
-        self.credit = credit
-        self.period = period
-
-    def getCredit(self):
-        return self.credit
-
-    def getPeriod(self):
-        return self.period
-        
-    def interfaceChanged(self):
-        """Notify the front-end that a device has been added or removed.
-        """
-        pass
-        
 class NetifController(DevController):
     """Network interface controller. Handles all network devices for a domain.
     """
     
-    def __init__(self, vm, recreate=False):
-        DevController.__init__(self, vm, recreate=recreate)
+    def __init__(self, vm):
+        DevController.__init__(self, vm)
 
-    def initController(self, recreate=False, reboot=False):
-        self.destroyed = False
-        if reboot:
-            self.rebootDevices()
 
-    def destroyController(self, reboot=False):
-        """Destroy the controller and all devices.
-        """
-        self.destroyed = True
-        log.debug("Destroying netif domain=%d", self.getDomain())
-        self.destroyDevices(reboot=reboot)
+    def getDeviceDetails(self, config):
+        """@see DevController.getDeviceDetails"""
 
-    def sxpr(self):
-        val = ['netif', ['dom', self.getDomain()]]
-        return val
-    
-    def newDevice(self, id, config, recreate=False):
-        """Create a network device.
+        global next_devid
 
-        @param id: interface id
-        @param config: device configuration
-        @param recreate: recreate flag (true after xend restart)
-        """
-        return NetDev(self, id, config, recreate=recreate)
+        from xen.xend import XendRoot
+        xroot = XendRoot.instance()
 
-    def limitDevice(self, vif, credit, period):        
-        if vif not in self.devices:
-            raise XendError('device does not exist for credit limit: vif'
-                            + str(self.getDomain()) + '.' + str(vif))
-        
-        dev = self.devices[vif]
-        return dev.setCreditLimit(credit, period)
+        def _get_config_ipaddr(config):
+            val = []
+            for ipaddr in sxp.children(config, elt='ip'):
+                val.append(sxp.child0(ipaddr))
+            return val
+
+        devid = next_devid
+        next_devid += 1
+
+        script = os.path.join(xroot.network_script_dir,
+                              sxp.child_value(config, 'script',
+                                              xroot.get_vif_script()))
+        bridge = sxp.child_value(config, 'bridge',
+                                 xroot.get_vif_bridge())
+        mac = sxp.child_value(config, 'mac')
+        ipaddr = _get_config_ipaddr(config)
+
+        back = { 'script' : script,
+                 'mac' : mac,
+                 'bridge' : bridge,
+                 'handle' : "%i" % devid }
+        if ipaddr:
+            back['ip'] = ' '.join(ipaddr)
+
+        front = { 'handle' : "%i" % devid,
+                  'mac' : mac }
+
+        return (devid, back, front)
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py     Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/pciif.py     Mon Sep 19 10:51:05 2005
@@ -13,16 +13,22 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
+
 
 import types
 
-import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
+import xen.lowlevel.xc;
 
 from xen.xend import sxp
 from xen.xend.XendError import VmError
 
-from controller import Dev, DevController
+from xen.xend.server.DevController import DevController
+
+
+xc = xen.lowlevel.xc.new()
+
 
 def parse_pci(val):
     """Parse a pci field.
@@ -36,27 +42,32 @@
         v = val
     return v
 
-class PciDev(Dev):
 
-    def __init__(self, controller, id, config, recreate=False):
-        Dev.__init__(self, controller, id, config, recreate=recreate)
-        bus = sxp.child_value(self.config, 'bus')
-        if not bus:
-            raise VmError('pci: Missing bus')
-        dev = sxp.child_value(self.config, 'dev')
-        if not dev:
-            raise VmError('pci: Missing dev')
-        func = sxp.child_value(self.config, 'func')
-        if not func:
-            raise VmError('pci: Missing func')
-        try:
-            bus = parse_pci(bus)
-            dev = parse_pci(dev)
-            func = parse_pci(func)
-        except:
-            raise VmError('pci: invalid parameter')
+class PciController(DevController):
 
-    def attach(self, recreate=False, change=False):
+    def __init__(self, vm):
+        DevController.__init__(self, vm)
+
+
+    def getDeviceDetails(self, config):
+        """@see DevController.getDeviceDetails"""
+
+        def get_param(field):
+            try:
+                val = sxp.child_value(config, field)
+
+                if not val:
+                    raise VmError('pci: Missing %s config setting' % field)
+
+                return parse_pci(val)
+            except:
+                raise VmError('pci: Invalid config setting %s: %s' %
+                              (field, val))
+        
+        bus  = get_param('bus')
+        dev  = get_param('dev')
+        func = get_param('func')
+
         rc = xc.physdev_pci_access_modify(dom    = self.getDomain(),
                                           bus    = bus,
                                           dev    = dev,
@@ -64,13 +75,8 @@
                                           enable = True)
         if rc < 0:
             #todo non-fatal
-            raise VmError('pci: Failed to configure device: bus=%s dev=%s 
func=%s' %
-                          (bus, dev, func))
+            raise VmError(
+                'pci: Failed to configure device: bus=%s dev=%s func=%s' %
+                (bus, dev, func))
 
-    def destroy(self, change=False, reboot=False):
-        pass
-
-class PciController(DevController):
-
-    def newDevice(self, id, config, recreate=False):
-        return PciDev(self, id, config, recreate=recreate)
+        return (dev, {}, {})
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/tpmif.py
--- a/tools/python/xen/xend/server/tpmif.py     Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/tpmif.py     Mon Sep 19 10:51:05 2005
@@ -1,45 +1,47 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
 # Copyright (C) 2005 IBM Corporation
-#   Authort: Stefan Berger, stefanb@xxxxxxxxxx
-# Derived from netif.py:
-# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
+#   Author: Stefan Berger, stefanb@xxxxxxxxxx
+# Copyright (C) 2005 XenSource Ltd
+#============================================================================
+
 """Support for virtual TPM interfaces.
 """
 
-import random
+from xen.xend import sxp
+from xen.xend.XendLogging import log
 
-from xen.xend import sxp
-from xen.xend.XendError import XendError, VmError
-from xen.xend.XendLogging import log
-from xen.xend.XendRoot import get_component
-from xen.xend.xenstore import DBVar
+from xen.xend.server.DevController import DevController
 
-from xen.xend.server.controller import Dev, DevController
 
 class TPMifController(DevController):
     """TPM interface controller. Handles all TPM devices for a domain.
     """
 
-    def __init__(self, vm, recreate=False):
-        DevController.__init__(self, vm, recreate=recreate)
+    def __init__(self, vm):
+        DevController.__init__(self, vm)
 
-    def initController(self, recreate=False, reboot=False):
-        self.destroyed = False
 
-    def destroyController(self, reboot=False):
-        """Destroy the controller and all devices.
-        """
-        self.destroyed = True
-        self.destroyDevices(reboot=reboot)
+    def getDeviceDetails(self, config):
+        """@see DevController.getDeviceDetails"""
+        
+        devid = int(sxp.child_value(config, 'instance', '0'))
+        log.error("The domain has a TPM with instance %d." % devid)
 
-    def sxpr(self):
-        val = ['tpmif', ['dom', self.getDomain()]]
-        return val
+        back  = { 'instance' : "%i" % devid }
+        front = { 'handle' : "%i" % devid }
 
-    def newDevice(self, id, config, recreate=False):
-        """Create a TPM device.
-
-        @param id: interface id
-        @param config: device configuration
-        @param recreate: recreate flag (true after xend restart)
-        """
-        return None
+        return (devid, back, front)
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/usbif.py
--- a/tools/python/xen/xend/server/usbif.py     Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/usbif.py     Mon Sep 19 10:51:05 2005
@@ -1,185 +1,50 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
 # Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx>
 # Copyright (C) 2004 Intel Research Cambridge
 # Copyright (C) 2004 Mark Williamson <mark.williamson@xxxxxxxxxxxx>
+# Copyright (C) 2005 XenSource Ltd
+#============================================================================
+
+
 """Support for virtual USB hubs.
 """
 
-from xen.xend import sxp
-from xen.xend.XendLogging import log
-from xen.xend.XendError import XendError
-from xen.xend.xenstore import DBVar
-
-from xen.xend.server.controller import Dev, DevController
-
-class UsbBackend:
-    """Handler for the 'back-end' channel to a USB device driver domain
-    on behalf of a front-end domain.
-    """
-    def __init__(self, controller, id, dom):
-        self.controller = controller
-        self.id = id
-        self.destroyed = False
-        self.connected = False
-        self.connecting = False
-        self.frontendDomain = self.controller.getDomain()
-        self.backendDomain = dom
-
-    def init(self, recreate=False, reboot=False):
-        pass
-    
-    def __str__(self):
-        return ('<UsbifBackend frontend=%d backend=%d id=%d>'
-                % (self.frontendDomain,
-                   self.backendDomain,
-                   self.id))
-
-    def connect(self, recreate=False):
-        """Connect the controller to the usbif control interface.
-
-        @param recreate: true if after xend restart
-        """
-        log.debug("Connecting usbif %s", str(self))
-        if recreate or self.connected or self.connecting:
-            pass
-        
-    def destroy(self, reboot=False):
-        """Disconnect from the usbif control interface and destroy it.
-        """
-        self.destroyed = True
-        
-    def interfaceChanged(self):
-        pass
+from xen.xend.server.DevController import DevController
 
 
-class UsbDev(Dev):
+next_devid = 1
 
-    __exports__ = Dev.__exports__ + [
-        DBVar('port', ty='int'),
-        DBVar('path', ty='str'),
-        ]
-    
-    def __init__(self, controller, id, config, recreate=False):
-        Dev.__init__(self, controller, id, config, recreate=recreate)
-        self.port = id
-        self.path = None
-        self.frontendDomain = self.getDomain()
-        self.backendDomain = 0
-        self.configure(self.config, recreate=recreate)
-
-    def init(self, recreate=False, reboot=False):
-        self.destroyed = False
-        self.frontendDomain = self.getDomain()
-        
-    def configure(self, config, change=False, recreate=False):
-        if change:
-            raise XendError("cannot reconfigure usb")
-        #todo: FIXME: Use sxp access methods to get this value.
-        # Must not use direct indexing.
-        self.path = config[1][1]
-        
-        #todo: FIXME: Support configuring the backend domain.
-##         try:
-##             self.backendDomain = int(sxp.child_value(config, 'backend', 
'0'))
-##         except:
-##             raise XendError('invalid backend domain')
-
-    def attach(self, recreate=False, change=False):
-        if recreate:
-            pass
-        else:
-            self.attachBackend()
-        if change:
-            self.interfaceChanged()
-            
-    def sxpr(self):
-        val = ['usb',
-               ['id', self.id],
-               ['port', self.port],
-               ['path', self.path],
-               ]
-        return val
-
-    def getBackend(self):
-        return self.controller.getBackend(self.backendDomain)
-
-    def destroy(self, change=False, reboot=False):
-        """Destroy the device. If 'change' is true notify the front-end 
interface.
-
-        @param change: change flag
-        """
-        self.destroyed = True
-        log.debug("Destroying usb domain=%d id=%s", self.frontendDomain, 
self.id)
-        if change:
-            self.interfaceChanged()
-
-    def interfaceChanged(self):
-        """Tell the back-end to notify the front-end that a device has been
-        added or removed.
-        """
-        self.getBackend().interfaceChanged()
-
-    def attachBackend(self):
-        """Attach the device to its controller.
-
-        """
-        self.getBackend().connect()
 
 class UsbifController(DevController):
     """USB device interface controller. Handles all USB devices
     for a domain.
     """
     
-    def __init__(self, vm, recreate=False):
+    def __init__(self, vm):
         """Create a USB device controller.
         """
-        DevController.__init__(self, vm, recreate=recreate)
-        self.backends = {}
-        self.backendId = 0
+        DevController.__init__(self, vm)
 
-    def init(self, recreate=False, reboot=False):
-        self.destroyed = False
-        if reboot:
-            self.rebootBackends()
-            self.rebootDevices()
 
-    def sxpr(self):
-        val = ['usbif',
-               ['dom', self.getDomain()]]
-        return val
+    def getDeviceDetails(self, _):
+        """@see DevController.getDeviceDetails"""
 
-    def newDevice(self, id, config, recreate=False):
-        return UsbDev(self, id, config, recreate=recreate)
+        global next_devid
 
-    def destroyController(self, reboot=False):
-        """Destroy the controller and all devices.
-        """
-        self.destroyed = True
-        log.debug("Destroying blkif domain=%d", self.getDomain())
-        self.destroyDevices(reboot=reboot)
-        self.destroyBackends(reboot=reboot)
+        devid = next_devid
+        next_devid += 1
 
-    def rebootBackends(self):
-        for backend in self.backends.values():
-            backend.init(reboot=True)
-
-    def getBackendById(self, id):
-        return self.backends.get(id)
-
-    def getBackendByDomain(self, dom):
-        for backend in self.backends.values():
-            if backend.backendDomain == dom:
-                return backend
-        return None
-
-    def getBackend(self, dom):
-        backend = self.getBackendByDomain(dom)
-        if backend: return backend
-        backend = UsbBackend(self, self.backendId, dom)
-        self.backendId += 1
-        self.backends[backend.getId()] = backend
-        backend.init()
-        return backend
-    
-    def destroyBackends(self, reboot=False):
-        for backend in self.backends.values():
-            backend.destroy(reboot=reboot)
+        return (devid, {}, {})
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/xenstore/xsobj.py
--- a/tools/python/xen/xend/xenstore/xsobj.py   Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/xenstore/xsobj.py   Mon Sep 19 10:51:05 2005
@@ -469,9 +469,6 @@
             n = n._addChild(x)
         return n
 
-    def getDB(self):
-        return self.__db__
-
     def setDB(self, db):
         if (db is not None) and not isinstance(db, XenNode):
             raise ValueError("invalid db")
diff -r cedb89d6b707 -r 308260e5868c 
tools/python/xen/xend/xenstore/xstransact.py
--- a/tools/python/xen/xend/xenstore/xstransact.py      Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/xenstore/xstransact.py      Mon Sep 19 10:51:05 2005
@@ -67,7 +67,12 @@
                 if not isinstance(d, dict):
                     raise TypeError
                 for key in d.keys():
-                    self._write(key, d[key], create, excl)
+                    try:
+                        self._write(key, d[key], create, excl)
+                    except TypeError, msg:
+                        raise TypeError('Writing %s: %s: %s' %
+                                        (key, str(d[key]), msg))
+                        
         elif isinstance(args[0], list):
             for l in args:
                 if not len(l) == 2:
@@ -84,10 +89,15 @@
         return xshandle().rm(path)
 
     def remove(self, *args):
-        if len(args) == 0:
-            raise TypeError
-        for key in args:
-            self._remove(key)
+        """If no arguments are given, remove this transaction's path.
+        Otherwise, treat each argument as a subpath to this transaction's
+        path, and remove each of those instead.
+        """
+        if len(args) == 0:
+            xshandle().rm(self.path)
+        else:
+            for key in args:
+                self._remove(key)
 
     def _list(self, key):
         path = "%s/%s" % (self.path, key)
@@ -146,8 +156,8 @@
 
     def Read(cls, path, *args):
         while True:
-            try:
-                t = cls(path)
+            t = cls(path)
+            try:
                 v = t.read(*args)
                 t.commit()
                 return v
@@ -165,8 +175,8 @@
 
     def Write(cls, path, *args, **opts):
         while True:
-            try:
-                t = cls(path)
+            t = cls(path)
+            try:
                 t.write(*args, **opts)
                 t.commit()
                 return
@@ -183,9 +193,13 @@
     Write = classmethod(Write)
 
     def Remove(cls, path, *args):
-        while True:
-            try:
-                t = cls(path)
+        """If only one argument is given (path), remove it.  Otherwise, treat
+        each further argument as a subpath to the given path, and remove each
+        of those instead.  This operation is performed inside a transaction.
+        """
+        while True:
+            t = cls(path)
+            try:
                 t.remove(*args)
                 t.commit()
                 return
@@ -203,8 +217,8 @@
 
     def List(cls, path, *args):
         while True:
-            try:
-                t = cls(path)
+            t = cls(path)
+            try:
                 v = t.list(*args)
                 t.commit()
                 return v
@@ -222,8 +236,8 @@
 
     def Gather(cls, path, *args):
         while True:
-            try:
-                t = cls(path)
+            t = cls(path)
+            try:
                 v = t.gather(*args)
                 t.commit()
                 return v
@@ -241,8 +255,8 @@
 
     def Store(cls, path, *args):
         while True:
-            try:
-                t = cls(path)
+            t = cls(path)
+            try:
                 v = t.store(*args)
                 t.commit()
                 return v
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/xenstore/xswatch.py
--- a/tools/python/xen/xend/xenstore/xswatch.py Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/xenstore/xswatch.py Mon Sep 19 10:51:05 2005
@@ -1,4 +1,5 @@
 # Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 
 # This file is subject to the terms and conditions of the GNU General
 # Public License.  See the file "COPYING" in the main directory of
@@ -15,7 +16,7 @@
     xs = None
     xslock = threading.Lock()
     
-    def __init__(self, path, fn, args=(), kwargs={}):
+    def __init__(self, path, fn, *args, **kwargs):
         self.fn = fn
         self.args = args
         self.kwargs = kwargs
@@ -46,11 +47,11 @@
         cls.threadcond.release()
         while True:
             try:
-                (ord, owr, oer) = select.select([ cls.xs ], [], [])
+                (fd, _1, _2) = select.select([ cls.xs ], [], [])
                 cls.xslock.acquire()
                 # reconfirm ready to read with lock
-                (ord, owr, oer) = select.select([ cls.xs ], [], [], 0.001)
-                if not cls.xs in ord:
+                (fd, _1, _2) = select.select([ cls.xs ], [], [], 0.001)
+                if not cls.xs in fd:
                     cls.xslock.release()
                     continue
                 we = cls.xs.read_watch()
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xm/create.py     Mon Sep 19 10:51:05 2005
@@ -141,7 +141,7 @@
           use="Domain memory in MB.")
 
 gopts.var('ssidref', val='SSIDREF',
-          fn=set_u32, default=-1, 
+          fn=set_u32, default=0, 
           use="Security Identifier.")
 
 gopts.var('maxmem', val='MEMORY',
diff -r cedb89d6b707 -r 308260e5868c 
tools/python/xen/xend/server/DevController.py
--- /dev/null   Mon Sep 19 09:14:41 2005
+++ b/tools/python/xen/xend/server/DevController.py     Mon Sep 19 10:51:05 2005
@@ -0,0 +1,203 @@
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
+#============================================================================
+
+
+from xen.xend import sxp
+from xen.xend.XendError import VmError
+from xen.xend.XendLogging import log
+from xen.xend.xenstore.xstransact import xstransact
+
+
+class DevController:
+    """Abstract base class for a device controller.  Device controllers create
+    appropriate entries in the store to trigger the creation, reconfiguration,
+    and destruction of devices in guest domains.  Each subclass of
+    DevController is responsible for a particular device-class, and
+    understands the details of configuration specific to that device-class.
+
+    DevController itself provides the functionality common to all device
+    creation tasks, as well as providing an interface to XendDomainInfo for
+    triggering those events themselves.
+    """
+
+    # Set when registered.
+    deviceClass = None
+
+
+    ## public:
+
+    def __init__(self, vm):
+        self.vm = vm
+
+
+    def createDevice(self, config):
+        """Trigger the creation of a device with the given configuration.
+
+        @return The ID for the newly created device.
+        """
+        (devid, back, front) = self.getDeviceDetails(config)
+
+        self.writeDetails(config, devid, back, front)
+
+        return devid
+
+
+    def reconfigureDevice(self, devid, config):
+        """Reconfigure the specified device.
+
+        The implementation here just raises VmError.  This may be overridden
+        by those subclasses that can reconfigure their devices.
+        """
+        raise VmError('%s devices may not be reconfigured' % self.deviceClass)
+
+
+    def destroyDevice(self, devid):
+        """Destroy the specified device.
+
+        The implementation here simply deletes the appropriate paths from
+        the store.  This may be overridden by subclasses who need to perform
+        other tasks on destruction.
+        """
+
+        frontpath = self.frontendPath(devid)
+        backpath = xstransact.Read("%s/backend" % frontpath)
+
+        xstransact.Remove(frontpath)
+        xstransact.Remove(backpath)
+
+
+    def sxpr(self, devid):
+        """@return an s-expression describing the specified device.
+        """
+        return [self.deviceClass, ['dom', self.vm.getDomain(),
+                                   'id', devid]]
+
+
+    ## protected:
+
+    def getDeviceDetails(self, config):
+        """Compute the details for creation of a device corresponding to the
+        given configuration.  These details consist of a tuple of (devID,
+        backDetails, frontDetails), where devID is the ID for the new device,
+        and backDetails and frontDetails are the device configuration
+        specifics for the backend and frontend respectively.
+
+        backDetails and frontDetails should be dictionaries, the keys and
+        values of which will be used as paths in the store.  There is no need
+        for these dictionaries to include the references from frontend to
+        backend, nor vice versa, as these will be handled by DevController.
+
+        Abstract; must be implemented by every subclass.
+
+        @return (devID, backDetails, frontDetails), as specified above.
+        """
+
+        raise NotImplementedError()
+
+
+    def getDomain(self):
+        """Stub to {@link XendDomainInfo.getDomain}, for use by our
+        subclasses.
+        """
+        return self.vm.getDomain()
+
+
+    def allocateDeviceID(self):
+        """Allocate a device ID, allocating them consecutively on a
+        per-domain, per-device-class basis, and using the store to record the
+        next available ID.
+
+        This method is available to our subclasses, though it is not
+        compulsory to use it; subclasses may prefer to allocate IDs based upon
+        the device configuration instead.
+        """
+        path = self.frontendMiscPath()
+        t = xstransact(path)
+        try:
+            result = t.read("nextDeviceID")
+            if result:
+                result = int(result)
+            else:
+                result = 1
+            t.write("nextDeviceID", str(result + 1))
+            t.commit()
+            return result
+        except:
+            t.abort()
+            raise
+
+
+    ## private:
+
+    def writeDetails(self, config, devid, backDetails, frontDetails):
+        """Write the details in the store to trigger creation of a device.
+        The backend domain ID is taken from the given config, paths for
+        frontend and backend are computed, and these are written to the store
+        appropriately, including references from frontend to backend and vice
+        versa.
+
+        @param config The configuration of the device, as given to
+        {@link #createDevice}.
+        @param devid        As returned by {@link #getDeviceDetails}.
+        @param backDetails  As returned by {@link #getDeviceDetails}.
+        @param frontDetails As returned by {@link #getDeviceDetails}.
+        """
+
+        import xen.xend.XendDomain
+        backdom = xen.xend.XendDomain.instance().domain_lookup_by_name(
+            sxp.child_value(config, 'backend', '0'))
+
+        frontpath = self.frontendPath(devid)
+        backpath  = self.backendPath(backdom, devid)
+        
+        frontDetails.update({
+            'backend' : backpath,
+            'backend-id' : "%i" % backdom.getDomain()
+            })
+
+
+        backDetails.update({
+            'domain' : self.vm.getName(),
+            'frontend' : frontpath,
+            'frontend-id' : "%i" % self.vm.getDomain()
+            })
+
+        log.debug('DevController: writing %s to %s.', str(frontDetails),
+                  frontpath)
+        log.debug('DevController: writing %s to %s.', str(backDetails),
+                  backpath)
+
+        xstransact.Write(frontpath, frontDetails)
+        xstransact.Write(backpath, backDetails)
+
+
+    def backendPath(self, backdom, devid):
+        """@param backdom [XendDomainInfo] The backend domain info."""
+
+        return "%s/backend/%s/%s/%d" % (backdom.getPath(),
+                                        self.deviceClass,
+                                        self.vm.getUuid(), devid)
+
+
+    def frontendPath(self, devid):
+        return "%s/device/%s/%d" % (self.vm.getPath(), self.deviceClass,
+                                    devid)
+
+
+    def frontendMiscPath(self):
+        return "%s/device-misc/%s" % (self.vm.getPath(), self.deviceClass)
diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/controller.py
--- a/tools/python/xen/xend/server/controller.py        Mon Sep 19 09:14:41 2005
+++ /dev/null   Mon Sep 19 10:51:05 2005
@@ -1,423 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
-#============================================================================
-
-"""General support for controllers, which handle devices
-for a domain.
-"""
-
-from xen.xend.XendError import XendError
-from xen.xend.xenstore import DBVar
-
-DEBUG = 0
-
-class DevControllerTable:
-    """Table of device controller classes, indexed by type name.
-    """
-
-    def __init__(self):
-        self.controllerClasses = {}
-
-    def getDevControllerClass(self, type):
-        return self.controllerClasses.get(type)
-
-    def addDevControllerClass(self, cls):
-        self.controllerClasses[cls.getType()] = cls
-
-    def delDevControllerClass(self, type):
-        if type in self.controllerClasses:
-            del self.controllerClasses[type]
-
-    def createDevController(self, type, vm, recreate=False):
-        cls = self.getDevControllerClass(type)
-        if not cls:
-            raise XendError("unknown device type: " + str(type))
-        return cls.createDevController(vm, recreate=recreate)
-
-def getDevControllerTable():
-    """Singleton constructor for the controller table.
-    """
-    global devControllerTable
-    try:
-        devControllerTable
-    except:
-        devControllerTable = DevControllerTable()
-    return devControllerTable
-
-def addDevControllerClass(name, cls):
-    """Add a device controller class to the controller table.
-    """
-    cls.type = name
-    getDevControllerTable().addDevControllerClass(cls)
-
-
-def isDevControllerClass(name):
-    """@return True if a device controller class has been registered with
-    the controller table under the given name."""
-    return name in getDevControllerTable().controllerClasses
-
-
-def createDevController(name, vm, recreate=False):
-    return getDevControllerTable().createDevController(name, vm, 
recreate=recreate)
-
-class DevController:
-    """Abstract class for a device controller attached to a domain.
-    A device controller manages all the devices of a given type for a domain.
-    There is exactly one device controller for each device type for
-    a domain.
-
-    """
-
-    # State:
-    # controller/<type> : for controller
-    # device/<type>/<id>   : for each device
-
-    def createDevController(cls, vm, recreate=False):
-        """Class method to create a dev controller.
-        """
-        ctrl = cls(vm, recreate=recreate)
-        ctrl.initController(recreate=recreate)
-        ctrl.exportToDB()
-        return ctrl
-
-    createDevController = classmethod(createDevController)
-
-    def getType(cls):
-        return cls.type
-
-    getType = classmethod(getType)
-
-    __exports__ = [
-        DBVar('type',      'str'),
-        DBVar('destroyed', 'bool'),
-        ]
-
-    # Set when registered.
-    type = None
-
-    def __init__(self, vm, recreate=False):
-        self.destroyed = False
-        self.vm = vm
-        self.db = self.getDB()
-        self.deviceId = 0
-        self.devices = {}
-        self.device_order = []
-
-    def getDB(self):
-        """Get the db node to use for a controller.
-        """
-        return self.vm.db.addChild("/controller/%s" % self.getType())
-
-    def getDevDB(self, id):
-        """Get the db node to use for a device.
-        """
-        return self.vm.db.addChild("/device/%s/%s" % (self.getType(), id))
-
-    def exportToDB(self, save=False):
-        self.db.exportToDB(self, fields=self.__exports__, save=save)
-
-    def importFromDB(self):
-        self.db.importFromDB(self, fields=self.__exports__)
-
-    def getDevControllerType(self):
-        return self.dctype
-
-    def getDomain(self):
-        return self.vm.getDomain()
-
-    def getDomainName(self):
-        return self.vm.getName()
-
-    def getDomainInfo(self):
-        return self.vm
-
-    
#----------------------------------------------------------------------------
-    # Subclass interface.
-    # Subclasses should define the unimplemented methods..
-    # Redefinitions must have the same arguments.
-
-    def initController(self, recreate=False, reboot=False):
-        """Initialise the controller. Called when the controller is
-        first created, and again after the domain is rebooted (with reboot 
True).
-        If called with recreate True (and reboot False) the controller is being
-        recreated after a xend restart.
-
-        As this can be a re-init (after reboot) any controller state should
-        be reset. For example the destroyed flag.
-        """
-        self.destroyed = False
-        if reboot:
-            self.rebootDevices()
-
-    def newDevice(self, id, config, recreate=False):
-        """Create a device with the given config.
-        Must be defined in subclass.
-        Called with recreate True when the device is being recreated after a
-        xend restart.
-
-        @return device
-        """
-        raise NotImplementedError()
-
-    def createDevice(self, config, recreate=False, change=False):
-        """Create a device and attach to its front- and back-ends.
-        If recreate is true the device is being recreated after a xend restart.
-        If change is true the device is a change to an existing domain,
-        i.e. it is being added at runtime rather than when the domain is 
created.
-        """
-        dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate)
-        if self.vm.recreate:
-            dev.importFromDB()
-        dev.init(recreate=recreate)
-        self.addDevice(dev)
-        if not recreate:
-            dev.exportToDB()
-        dev.attach(recreate=recreate, change=change)
-        dev.exportToDB()
-
-        return dev
-
-    def configureDevice(self, id, config, change=False):
-        """Reconfigure an existing device.
-        May be defined in subclass."""
-        dev = self.getDevice(id, error=True)
-        dev.configure(config, change=change)
-
-    def destroyDevice(self, id, change=False, reboot=False):
-        """Destroy a device.
-        May be defined in subclass.
-
-        If reboot is true the device is being destroyed for a domain reboot.
-
-        The device is not deleted, since it may be recreated later.
-        """
-        dev = self.getDevice(id, error=True)
-        dev.destroy(change=change, reboot=reboot)
-        return dev
-
-    def deleteDevice(self, id, change=True):
-        """Destroy a device and delete it.
-        Normally called to remove a device from a domain at runtime.
-        """
-        dev = self.destroyDevice(id, change=change)
-        self.removeDevice(dev)
-
-    def destroyController(self, reboot=False):
-        """Destroy all devices and clean up.
-        May be defined in subclass.
-        If reboot is true the controller is being destroyed for a domain 
reboot.
-        Called at domain shutdown.
-        """
-        self.destroyed = True
-        self.destroyDevices(reboot=reboot)
-
-    
#----------------------------------------------------------------------------
-    
-    def isDestroyed(self):
-        return self.destroyed
-
-    def getDevice(self, id, error=False):
-        dev = self.devices.get(int(id))
-        if error and not dev:
-            raise XendError("invalid device id: " + str(id))
-        return dev
-
-    def getDeviceIds(self):
-        return [ dev.getId() for dev in self.device_order ]
-
-    def getDevices(self):
-        return self.device_order
-
-    def getDeviceConfig(self, id):
-        return self.getDevice(id).getConfig()
-
-    def getDeviceConfigs(self):
-        return [ dev.getConfig() for dev in self.device_order ]
-
-    def getDeviceSxprs(self):
-        return [ dev.sxpr() for dev in self.device_order ]
-
-    def addDevice(self, dev):
-        self.devices[dev.getId()] = dev
-        self.device_order.append(dev)
-        return dev
-
-    def removeDevice(self, dev):
-        if dev.getId() in self.devices:
-            del self.devices[dev.getId()]
-        if dev in self.device_order:
-            self.device_order.remove(dev)
-
-    def rebootDevices(self):
-        for dev in self.getDevices():
-            dev.reboot()
-
-    def destroyDevices(self, reboot=False):
-        """Destroy all devices.
-        """
-        for dev in self.getDevices():
-            dev.destroy(reboot=reboot)
-
-    def getMaxDeviceId(self):
-        maxid = 0
-        for id in self.devices:
-            if id > maxid:
-                maxid = id
-        return maxid
-
-    def nextDeviceId(self):
-        id = self.deviceId
-        self.deviceId += 1
-        return id
-
-    def getDeviceCount(self):
-        return len(self.devices)
-
-class Dev:
-    """Abstract class for a device attached to a device controller.
-
-    @ivar id:        identifier
-    @type id:        int
-    @ivar controller: device controller
-    @type controller: DevController
-    """
-    
-    # ./status       : need 2: actual and requested?
-    # down-down: initial.
-    # up-up: fully up.
-    # down-up: down requested, still up. Watch front and back, when both
-    # down go to down-down. But what if one (or both) is not connected?
-    # Still have front/back trees with status? Watch front/status, back/status?
-    # up-down: up requested, still down.
-    # Back-end watches ./status, front/status
-    # Front-end watches ./status, back/status
-    # i.e. each watches the other 2.
-    # Each is status/request status/actual?
-    #
-    # backend?
-    # frontend?
-
-    __exports__ = [
-        DBVar('id',        ty='int'),
-        DBVar('type',      ty='str'),
-        DBVar('config',    ty='sxpr'),
-        DBVar('destroyed', ty='bool'),
-        ]
-
-    def __init__(self, controller, id, config, recreate=False):
-        self.controller = controller
-        self.id = id
-        self.config = config
-        self.destroyed = False
-        self.type = self.getType()
-
-        self.db = controller.getDevDB(id)
-
-    def exportToDB(self, save=False):
-        self.db.exportToDB(self, fields=self.__exports__, save=save)
-
-    def importFromDB(self):
-        self.db.importFromDB(self, fields=self.__exports__)
-
-    def getDomain(self):
-        return self.controller.getDomain()
-
-    def getDomainName(self):
-        return self.controller.getDomainName()
-
-    def getDomainInfo(self):
-        return self.controller.getDomainInfo()
-    
-    def getController(self):
-        return self.controller
-
-    def getType(self):
-        return self.controller.getType()
-
-    def getId(self):
-        return self.id
-
-    def getConfig(self):
-        return self.config
-
-    def isDestroyed(self):
-        return self.destroyed
-
-    
#----------------------------------------------------------------------------
-    # Subclass interface.
-    # Define methods in subclass as needed.
-    # Redefinitions must have the same arguments.
-
-    def init(self, recreate=False, reboot=False):
-        """Initialization. Called on initial create (when reboot is False)
-        and on reboot (when reboot is True). When xend is restarting is
-        called with recreate True. Define in subclass if needed.
-
-        Device instance variables must be defined in the class constructor,
-        but given null or default values. The real values should be initialised
-        in this method. This allows devices to be re-initialised.
-
-        Since this can be called to re-initialise a device any state flags
-        should be reset.
-        """
-        self.destroyed = False
-
-    def attach(self, recreate=False, change=False):
-        """Attach the device to its front and back ends.
-        Define in subclass if needed.
-        """
-        pass
-
-    def reboot(self):
-        """Reconnect the device when the domain is rebooted.
-        """
-        self.init(reboot=True)
-        self.attach()
-
-    def sxpr(self):
-        """Get the s-expression for the deivice.
-        Implement in a subclass if needed.
-
-        @return: sxpr
-        """
-        return self.getConfig()
-
-    def configure(self, config, change=False):
-        """Reconfigure the device.
-
-        Implement in subclass.
-        """
-        raise NotImplementedError()
-
-    def refresh(self):
-        """Refresh the device..
-        Default no-op. Define in subclass if needed.
-        """
-        pass
-
-    def destroy(self, change=False, reboot=False):
-        """Destroy the device.
-        If change is True notify destruction (runtime change).
-        If reboot is True the device is being destroyed for a reboot.
-        Redefine in subclass if needed.
-
-        Called at domain shutdown and when a device is deleted from
-        a running domain (with change True).
-        """
-        self.destroyed = True
-        pass
-    
-    
#----------------------------------------------------------------------------

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.