WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[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

<Prev in Thread] Current Thread [Next in Thread>