ia64/xen-unstable

changeset 5388:cb9679a15acd

bitkeeper revision 1.1662.1.21 (42a80585xAt7ZrRcqmCRm3HvTrL7Mg)

Many files:
Switch to xenstore for storing persistent information.
Signed-off-by: Mike Wray <mike.wray@hp.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Jun 09 09:01:57 2005 +0000 (2005-06-09)
parents a4c65af08cf4
children ccd879d035da
files tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/XendRoot.py tools/python/xen/xend/XendVnet.py tools/python/xen/xend/image.py tools/python/xen/xend/server/blkif.py tools/python/xen/xend/server/channel.py tools/python/xen/xend/server/console.py tools/python/xen/xend/server/controller.py tools/python/xen/xend/server/netif.py tools/python/xen/xend/server/usbif.py tools/python/xen/xend/xenstore/xsobj.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomain.py	Thu Jun 09 09:00:58 2005 +0000
     1.2 +++ b/tools/python/xen/xend/XendDomain.py	Thu Jun 09 09:01:57 2005 +0000
     1.3 @@ -23,7 +23,8 @@ from xen.xend.XendLogging import log
     1.4  from xen.xend import scheduler
     1.5  from xen.xend.server import channel
     1.6  from xen.xend.server import relocate
     1.7 -from xen.xend import XendDB
     1.8 +from xen.xend.uuid import getUuid
     1.9 +from xen.xend.xenstore import XenNode, DBMap
    1.10  
    1.11  __all__ = [ "XendDomain" ]
    1.12  
    1.13 @@ -40,9 +41,6 @@ class XendDomain:
    1.14      """Index of all domains. Singleton.
    1.15      """
    1.16  
    1.17 -    """Path to domain database."""
    1.18 -    dbpath = "domain"
    1.19 -
    1.20      """Dict of domain info indexed by domain id."""
    1.21      domains = None
    1.22      
    1.23 @@ -53,7 +51,7 @@ class XendDomain:
    1.24          # So we stuff the XendDomain instance (self) into xroot's components.
    1.25          xroot.add_component("xen.xend.XendDomain", self)
    1.26          self.domains = XendDomainDict()
    1.27 -        self.db = XendDB.XendDB(self.dbpath)
    1.28 +        self.dbmap = DBMap(db=XenNode("/domain"))
    1.29          eserver.subscribe('xend.virq', self.onVirq)
    1.30          self.initial_refresh()
    1.31  
    1.32 @@ -96,11 +94,18 @@ class XendDomain:
    1.33          """Refresh initial domain info from db.
    1.34          """
    1.35          doms = self.xen_domains()
    1.36 -        for config in self.db.fetchall("").values():
    1.37 -            domid = int(sxp.child_value(config, 'id'))
    1.38 -            if domid in doms:
    1.39 +        self.dbmap.readDB()
    1.40 +        for domdb in self.dbmap.values():
    1.41 +            try:
    1.42 +                domid = int(domdb.id)
    1.43 +            except:
    1.44 +                domid = None
    1.45 +            # XXX if domid in self.domains, then something went wrong
    1.46 +            if (domid is None) or (domid in self.domains):
    1.47 +                domdb.delete()
    1.48 +            elif domid in doms:
    1.49                  try:
    1.50 -                    self._new_domain(config, doms[domid])
    1.51 +                    self._new_domain(domdb, doms[domid]) 
    1.52                  except Exception, ex:
    1.53                      log.exception("Error recreating domain info: id=%d", domid)
    1.54                      self._delete_domain(domid)
    1.55 @@ -108,27 +113,20 @@ class XendDomain:
    1.56                  self._delete_domain(domid)
    1.57          self.refresh(cleanup=True)
    1.58  
    1.59 -    def sync_domain(self, info):
    1.60 -        """Sync info for a domain to disk.
    1.61 -
    1.62 -        info	domain info
    1.63 -        """
    1.64 -        self.db.save(str(info.id), info.sxpr())
    1.65 -
    1.66      def close(self):
    1.67          pass
    1.68  
    1.69 -    def _new_domain(self, savedinfo, info):
    1.70 +    def _new_domain(self, db, info):
    1.71          """Create a domain entry from saved info.
    1.72  
    1.73 -        @param savedinfo: saved info from the db
    1.74 +        @param db:        saved info from the db
    1.75          @param info:      domain info from xen
    1.76          @return: domain
    1.77          """
    1.78 -        uuid = sxp.child_value(savedinfo, 'uuid')
    1.79 -        dominfo = XendDomainInfo.recreate(savedinfo, info, uuid)
    1.80 +        log.error(db)
    1.81 +        log.error(db.uuid)
    1.82 +        dominfo = XendDomainInfo.recreate(db, info)
    1.83          self.domains[dominfo.id] = dominfo
    1.84 -        self.sync_domain(dominfo)
    1.85          return dominfo
    1.86  
    1.87      def _add_domain(self, info, notify=True):
    1.88 @@ -141,11 +139,11 @@ class XendDomain:
    1.89          for i, d in self.domains.items():
    1.90              if i != d.id:
    1.91                  del self.domains[i]
    1.92 -                self.db.delete(str(i))
    1.93 +                self.dbmap.delete(d.uuid)
    1.94          if info.id in self.domains:
    1.95              notify = False
    1.96          self.domains[info.id] = info
    1.97 -        self.sync_domain(info)
    1.98 +        info.exportToDB(save=True)
    1.99          if notify:
   1.100              eserver.inject('xend.domain.create', [info.name, info.id])
   1.101  
   1.102 @@ -155,12 +153,26 @@ class XendDomain:
   1.103          @param id:     domain id
   1.104          @param notify: send a domain died event if true
   1.105          """
   1.106 +        try:
   1.107 +            if self.xen_domain(id):
   1.108 +                return
   1.109 +        except:
   1.110 +            pass
   1.111          info = self.domains.get(id)
   1.112          if info:
   1.113              del self.domains[id]
   1.114 -            self.db.delete(str(id))
   1.115 +            info.cleanup()
   1.116 +            info.delete()
   1.117              if notify:
   1.118                  eserver.inject('xend.domain.died', [info.name, info.id])
   1.119 +        # XXX this should not be needed
   1.120 +        for domdb in self.dbmap.values():
   1.121 +            try:
   1.122 +                domid = int(domdb.id)
   1.123 +            except:
   1.124 +                domid = None
   1.125 +            if (domid is None) or (domid == id):
   1.126 +                domdb.delete()
   1.127  
   1.128      def reap(self):
   1.129          """Look for domains that have crashed or stopped.
   1.130 @@ -263,8 +275,7 @@ class XendDomain:
   1.131          @param config: configuration
   1.132          @return: domain
   1.133          """
   1.134 -        dominfo = XendDomainInfo.create(config)
   1.135 -        self._add_domain(dominfo)
   1.136 +        dominfo = XendDomainInfo.create(self.dbmap, config)
   1.137          return dominfo
   1.138  
   1.139      def domain_restart(self, dominfo):
   1.140 @@ -277,7 +288,6 @@ class XendDomain:
   1.141                         [dominfo.name, dominfo.id, "begin"])
   1.142          try:
   1.143              dominfo.restart()
   1.144 -            self._add_domain(dominfo)
   1.145              log.info('Restarted domain name=%s id=%s', dominfo.name, dominfo.id)
   1.146              eserver.inject("xend.domain.restart",
   1.147                             [dominfo.name, dominfo.id, "success"])
   1.148 @@ -297,8 +307,7 @@ class XendDomain:
   1.149          """
   1.150          config = sxp.child_value(vmconfig, 'config')
   1.151          uuid = sxp.child_value(vmconfig, 'uuid')
   1.152 -        dominfo = XendDomainInfo.restore(config, uuid=uuid)
   1.153 -        self._add_domain(dominfo)
   1.154 +        dominfo = XendDomainInfo.restore(self.dbmap, config, uuid=uuid)
   1.155          return dominfo
   1.156  
   1.157      def domain_restore(self, src, progress=False):
   1.158 @@ -330,8 +339,12 @@ class XendDomain:
   1.159              try:
   1.160                  info = self.xen_domain(id)
   1.161                  if info:
   1.162 -                    log.info("Creating entry for unknown domain: id=%d", id)
   1.163 -                    dominfo = XendDomainInfo.recreate(None, info)
   1.164 +                    uuid = getUuid()
   1.165 +                    log.info(
   1.166 +                        "Creating entry for unknown domain: id=%d uuid=%s",
   1.167 +                        id, uuid)
   1.168 +                    db = self.dbmap.addChild(uuid)
   1.169 +                    dominfo = XendDomainInfo.recreate(db, info)
   1.170                      self._add_domain(dominfo)
   1.171              except Exception, ex:
   1.172                  log.exception("Error creating domain info: id=%d", id)
   1.173 @@ -593,7 +606,7 @@ class XendDomain:
   1.174          """
   1.175          dominfo = self.domain_lookup(id)
   1.176          val = dominfo.device_create(devconfig)
   1.177 -        self.sync_domain(dominfo)
   1.178 +        dominfo.exportToDB()
   1.179          return val
   1.180  
   1.181      def domain_device_configure(self, id, devconfig, devid):
   1.182 @@ -606,7 +619,7 @@ class XendDomain:
   1.183          """
   1.184          dominfo = self.domain_lookup(id)
   1.185          val = dominfo.device_configure(devconfig, devid)
   1.186 -        self.sync_domain(dominfo)
   1.187 +        dominfo.exportToDB()
   1.188          return val
   1.189      
   1.190      def domain_device_refresh(self, id, type, devid):
   1.191 @@ -618,7 +631,7 @@ class XendDomain:
   1.192          """
   1.193          dominfo = self.domain_lookup(id)
   1.194          val = dominfo.device_refresh(type, devid)
   1.195 -        self.sync_domain(dominfo)
   1.196 +        dominfo.exportToDB()
   1.197          return val
   1.198  
   1.199      def domain_device_destroy(self, id, type, devid):
   1.200 @@ -630,7 +643,7 @@ class XendDomain:
   1.201          """
   1.202          dominfo = self.domain_lookup(id)
   1.203          val = dominfo.device_destroy(type, devid)
   1.204 -        self.sync_domain(dominfo)
   1.205 +        dominfo.exportToDB()
   1.206          return val
   1.207  
   1.208      def domain_devtype_ls(self, id, type):
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Jun 09 09:00:58 2005 +0000
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Jun 09 09:01:57 2005 +0000
     2.3 @@ -30,6 +30,7 @@ from XendError import XendError, VmError
     2.4  from xen.xend.XendRoot import get_component
     2.5  
     2.6  from xen.xend.uuid import getUuid
     2.7 +from xen.xend.xenstore import DBVar
     2.8  
     2.9  """Flag for a block device backend domain."""
    2.10  SIF_BLK_BE_DOMAIN = (1<<4)
    2.11 @@ -145,94 +146,92 @@ class XendDomainInfo:
    2.12      """
    2.13      MINIMUM_RESTART_TIME = 20
    2.14  
    2.15 -    def _create(cls, uuid=None):
    2.16 -        """Create a vm object with a uuid.
    2.17 +    def create(cls, parentdb, config):
    2.18 +        """Create a VM from a configuration.
    2.19  
    2.20 -        @param uuid uuid to use
    2.21 -        @return vm
    2.22 -        """
    2.23 -        if uuid is None:
    2.24 -            uuid = getUuid()
    2.25 -        vm = cls()
    2.26 -        vm.uuid = uuid
    2.27 -        return vm
    2.28 -
    2.29 -    _create = classmethod(_create)
    2.30 -
    2.31 -    def create(cls, config):
    2.32 -        """Create a VM from a configuration.
    2.33 -        If a vm has been partially created and there is an error it
    2.34 -        is destroyed.
    2.35 -
    2.36 +        @param parentdb:  parent db
    2.37          @param config    configuration
    2.38          @raise: VmError for invalid configuration
    2.39          """
    2.40 -        vm = cls._create()
    2.41 +        uuid = getUuid()
    2.42 +        db = parentdb.addChild(uuid)
    2.43 +        vm = cls(db)
    2.44          vm.construct(config)
    2.45 +        vm.saveDB(sync=True)
    2.46          return vm
    2.47  
    2.48      create = classmethod(create)
    2.49  
    2.50 -    def recreate(cls, savedinfo, info, uuid=None):
    2.51 +    def recreate(cls, db, info):
    2.52          """Create the VM object for an existing domain.
    2.53  
    2.54 -        @param savedinfo: saved info from the domain DB
    2.55 +        @param db:        domain db
    2.56          @param info:      domain info from xc
    2.57 -        @param uuid:      uuid to use
    2.58 -        @type  info:      xc domain dict
    2.59          """
    2.60 -        vm = cls._create(uuid=uuid)
    2.61 +        dom = info['dom']
    2.62 +        vm = cls(db)
    2.63 +        db.readDB()
    2.64 +        vm.importFromDB()
    2.65 +        config = vm.config
    2.66 +        log.debug('info=' + str(info))
    2.67 +        log.debug('config=' + prettyprintstring(config))
    2.68  
    2.69 -        log.debug('savedinfo=' + prettyprintstring(savedinfo))
    2.70 -        log.debug('info=' + str(info))
    2.71 -
    2.72 -        vm.recreate = True
    2.73 -        vm.savedinfo = savedinfo
    2.74 -        vm.setdom(info['dom'])
    2.75 +        vm.setdom(dom)
    2.76          vm.memory = info['mem_kb']/1024
    2.77  
    2.78 -        start_time = sxp.child_value(savedinfo, 'start_time')
    2.79 -        if start_time is not None:
    2.80 -            vm.start_time = float(start_time)
    2.81 -        vm.restart_state = sxp.child_value(savedinfo, 'restart_state')
    2.82 -        vm.restart_count = int(sxp.child_value(savedinfo, 'restart_count', 0))
    2.83 -        restart_time = sxp.child_value(savedinfo, 'restart_time')
    2.84 -        if restart_time is not None:
    2.85 -            vm.restart_time = float(restart_time)
    2.86 -        config = sxp.child_value(savedinfo, 'config')
    2.87 +        if config:
    2.88 +            try:
    2.89 +                vm.recreate = True
    2.90 +                vm.construct(config)
    2.91 +            finally:
    2.92 +                vm.recreate = False
    2.93 +        else:
    2.94 +            vm.setName("Domain-%d" % dom)
    2.95  
    2.96 -        if config:
    2.97 -            vm.construct(config)
    2.98 -        else:
    2.99 -            vm.setName(sxp.child_value(savedinfo, 'name',
   2.100 -                                       "Domain-%d" % info['dom']))
   2.101 -        vm.recreate = False
   2.102 -        vm.savedinfo = None
   2.103 -
   2.104 +        vm.exportToDB(save=True)
   2.105          return vm
   2.106  
   2.107      recreate = classmethod(recreate)
   2.108  
   2.109 -    def restore(cls, config, uuid=None):
   2.110 +    def restore(cls, parentdb, config, uuid=None):
   2.111          """Create a domain and a VM object to do a restore.
   2.112  
   2.113 +        @param parentdb:  parent db
   2.114          @param config:    domain configuration
   2.115          @param uuid:      uuid to use
   2.116          """
   2.117 -        vm = cls._create(uuid=uuid)
   2.118 +        db = parentdb.addChild(uuid)
   2.119 +        vm = cls(db)
   2.120          dom = xc.domain_create()
   2.121          vm.setdom(dom)
   2.122          vm.dom_construct(vm.id, config)
   2.123 +        vm.saveDB(sync=True)
   2.124          return vm
   2.125  
   2.126      restore = classmethod(restore)
   2.127  
   2.128 -    def __init__(self):
   2.129 +    __exports__ = [
   2.130 +        DBVar('id',            ty='str'),
   2.131 +        DBVar('name',          ty='str'),
   2.132 +        DBVar('uuid',          ty='str'),
   2.133 +        DBVar('config',        ty='sxpr'),
   2.134 +        DBVar('start_time',    ty='float'),
   2.135 +        DBVar('state',         ty='str'),
   2.136 +        DBVar('store_mfn',     ty='long'),
   2.137 +        DBVar('restart_mode',  ty='str'),
   2.138 +        DBVar('restart_state', ty='str'),
   2.139 +        DBVar('restart_time',  ty='float'),
   2.140 +        DBVar('restart_count', ty='int'),
   2.141 +        ]
   2.142 +    
   2.143 +    def __init__(self, db):
   2.144 +        self.db = db
   2.145 +        self.uuid = db.getName()
   2.146 +
   2.147          self.recreate = 0
   2.148          self.restore = 0
   2.149          
   2.150          self.config = None
   2.151 -        self.uuid = None
   2.152          self.id = None
   2.153          self.cpu_weight = 1
   2.154          self.start_time = None
   2.155 @@ -262,23 +261,39 @@ class XendDomainInfo:
   2.156          self.restart_count = 0
   2.157          
   2.158          self.console_port = None
   2.159 -        self.savedinfo = None
   2.160          self.vcpus = 1
   2.161          self.bootloader = None
   2.162  
   2.163 +    def setDB(self, db):
   2.164 +        self.db = db
   2.165 +
   2.166 +    def saveDB(self, save=False, sync=False):
   2.167 +        self.db.saveDB(save=save, sync=sync)
   2.168 +
   2.169 +    def exportToDB(self, save=False, sync=False):
   2.170 +        if self.channel:
   2.171 +            self.channel.saveToDB(self.db.addChild("channel"))
   2.172 +        if self.store_channel:
   2.173 +            self.store_channel.saveToDB(self.db.addChild("store_channel"))
   2.174 +        self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
   2.175 +
   2.176 +    def importFromDB(self):
   2.177 +        self.db.importFromDB(self, fields=self.__exports__)
   2.178 +
   2.179      def setdom(self, dom):
   2.180          """Set the domain id.
   2.181  
   2.182          @param dom: domain id
   2.183          """
   2.184          self.id = int(dom)
   2.185 +        #self.db.id = self.id
   2.186  
   2.187      def getDomain(self):
   2.188          return self.id
   2.189  
   2.190      def setName(self, name):
   2.191          self.name = name
   2.192 -        #self.db.name = self.name
   2.193 +        self.db.name = self.name
   2.194  
   2.195      def getName(self):
   2.196          return self.name
   2.197 @@ -301,6 +316,7 @@ class XendDomainInfo:
   2.198              self.state = state
   2.199              self.state_updated.notifyAll()
   2.200          self.state_updated.release()
   2.201 +        self.saveDB()
   2.202  
   2.203      def state_wait(self, state):
   2.204          self.state_updated.acquire()
   2.205 @@ -484,6 +500,7 @@ class XendDomainInfo:
   2.206              self.configure_restart()
   2.207              self.construct_image()
   2.208              self.configure()
   2.209 +            self.exportToDB()
   2.210          except Exception, ex:
   2.211              # Catch errors, cleanup and re-raise.
   2.212              print 'Domain construction error:', ex
   2.213 @@ -495,6 +512,7 @@ class XendDomainInfo:
   2.214      def register_domain(self):
   2.215          xd = get_component('xen.xend.XendDomain')
   2.216          xd._add_domain(self)
   2.217 +        self.exportToDB()
   2.218  
   2.219      def configure_cpus(self, config):
   2.220          try:
   2.221 @@ -528,42 +546,26 @@ class XendDomainInfo:
   2.222          """
   2.223          self.create_channel()
   2.224          self.image.createImage()
   2.225 -        #self.image.exportToDB()
   2.226 +        self.image.exportToDB()
   2.227          #if self.store_channel:
   2.228          #    self.db.introduceDomain(self.id,
   2.229          #                            self.store_mfn,
   2.230          #                            self.store_channel)
   2.231  
   2.232 -    def get_device_savedinfo(self, type, id):
   2.233 -        val = None
   2.234 -        if self.savedinfo is None:
   2.235 -            return val
   2.236 -        devices = sxp.child(self.savedinfo, 'devices')
   2.237 -        if devices is None:
   2.238 -            return val
   2.239 -        for d in sxp.children(devices, type):
   2.240 -            did = sxp.child_value(d, 'id')
   2.241 -            if did is None: continue
   2.242 -            if int(did) == id:
   2.243 -                val = d
   2.244 -                break
   2.245 -        return val
   2.246 -
   2.247 -    def get_device_recreate(self, type, id):
   2.248 -        return self.get_device_savedinfo(type, id) or self.recreate
   2.249 -
   2.250 -    def destroy(self):
   2.251 -        """Completely destroy the vm.
   2.252 +    def delete(self):
   2.253 +        """Delete the vm's db.
   2.254          """
   2.255 +        if self.dom_get(self.id):
   2.256 +            return
   2.257 +        self.id = None
   2.258 +        self.saveDB(sync=True)
   2.259          try:
   2.260 -            self.cleanup()
   2.261 +            # Todo: eventually will have to wait for devices to signal
   2.262 +            # destruction before can delete the db.
   2.263 +            if self.db:
   2.264 +                self.db.delete()
   2.265          except Exception, ex:
   2.266 -            log.warning("error in domain cleanup: %s", ex)
   2.267 -            pass
   2.268 -        try:
   2.269 -            self.destroy_domain()
   2.270 -        except Exception, ex:
   2.271 -            log.warning("error in domain destroy: %s", ex)
   2.272 +            log.warning("error in domain db delete: %s", ex)
   2.273              pass
   2.274  
   2.275      def destroy_domain(self):
   2.276 @@ -571,6 +573,18 @@ class XendDomainInfo:
   2.277          The domain will not finally go away unless all vm
   2.278          devices have been released.
   2.279          """
   2.280 +        if self.id is None:
   2.281 +            return
   2.282 +        try:
   2.283 +            xc.domain_destroy(dom=self.id)
   2.284 +        except Exception, err:
   2.285 +            log.exception("Domain destroy failed: %s", self.name)
   2.286 +
   2.287 +    def cleanup(self):
   2.288 +        """Cleanup vm resources: release devices.
   2.289 +        """
   2.290 +        self.state = STATE_VM_TERMINATED
   2.291 +        self.release_devices()
   2.292          if self.channel:
   2.293              try:
   2.294                  self.channel.close()
   2.295 @@ -583,23 +597,25 @@ class XendDomainInfo:
   2.296                  self.store_channel = None
   2.297              except:
   2.298                  pass
   2.299 +            #try:
   2.300 +            #    self.db.releaseDomain(self.id)
   2.301 +            #except Exception, ex:
   2.302 +            #    log.warning("error in domain release on xenstore: %s", ex)
   2.303 +            #    pass
   2.304          if self.image:
   2.305              try:
   2.306                  self.image.destroy()
   2.307                  self.image = None
   2.308              except:
   2.309                  pass
   2.310 -        if self.id is None: return 0
   2.311 -        try:
   2.312 -            xc.domain_destroy(dom=self.id)
   2.313 -        except Exception, err:
   2.314 -            log.exception("Domain destroy failed: %s", self.name)
   2.315  
   2.316 -    def cleanup(self):
   2.317 -        """Cleanup vm resources: release devices.
   2.318 +    def destroy(self):
   2.319 +        """Clenup vm and destroy domain.
   2.320          """
   2.321 -        self.state = STATE_VM_TERMINATED
   2.322 -        self.release_devices()
   2.323 +        self.cleanup()
   2.324 +        self.destroy_domain()
   2.325 +        self.saveDB()
   2.326 +        return 0
   2.327  
   2.328      def is_terminated(self):
   2.329          """Check if a domain has been terminated.
   2.330 @@ -639,27 +655,24 @@ class XendDomainInfo:
   2.331          if not self.restore:
   2.332              self.setdom(dom)
   2.333  
   2.334 -    def openChannel(self, name, local, remote):
   2.335 +    def openChannel(self, key, local, remote):
   2.336          """Create a channel to the domain.
   2.337          If saved info is available recreate the channel.
   2.338          
   2.339 +        @param key db key for the saved data (if any)
   2.340          @param local default local port
   2.341          @param remote default remote port
   2.342          """
   2.343 -        local = 0
   2.344 -        remote = 1
   2.345 -        if self.savedinfo:
   2.346 -            info = sxp.child(self.savedinfo, name)
   2.347 -            if info:
   2.348 -                local = int(sxp.child_value(info, "local_port", 0))
   2.349 -                remote = int(sxp.child_value(info, "remote_port", 1))
   2.350 -        chan = channelFactory().openChannel(self.id, local_port=local,
   2.351 -                                            remote_port=remote)
   2.352 +        db = self.db.addChild(key)
   2.353 +        chan = channelFactory().restoreFromDB(db, self.id, local, remote)
   2.354 +        #todo: save here?
   2.355 +        #chan.saveToDB(db)
   2.356          return chan
   2.357  
   2.358 -    def eventChannel(self, name):
   2.359 -        return EventChannel.interdomain(0, self.id)
   2.360 -
   2.361 +    def eventChannel(self, key):
   2.362 +        db = self.db.addChild(key)
   2.363 +        return EventChannel.restoreFromDB(db, 0, self.id)
   2.364 +        
   2.365      def create_channel(self):
   2.366          """Create the channels to the domain.
   2.367          """
   2.368 @@ -823,6 +836,7 @@ class XendDomainInfo:
   2.369              if self.bootloader:
   2.370                  self.config = self.bootloader_config()
   2.371              self.construct(self.config)
   2.372 +            self.saveDB()
   2.373          finally:
   2.374              self.restart_state = None
   2.375  
     3.1 --- a/tools/python/xen/xend/XendRoot.py	Thu Jun 09 09:00:58 2005 +0000
     3.2 +++ b/tools/python/xen/xend/XendRoot.py	Thu Jun 09 09:01:57 2005 +0000
     3.3 @@ -25,9 +25,6 @@ import sxp
     3.4  class XendRoot:
     3.5      """Root of the management classes."""
     3.6  
     3.7 -    """Default path to the root of the database."""
     3.8 -    dbroot_default = "/var/lib/xen/xend-db"
     3.9 -
    3.10      """Default path to the config file."""
    3.11      config_default = "/etc/xen/xend-config.sxp"
    3.12  
    3.13 @@ -82,7 +79,6 @@ class XendRoot:
    3.14      components = {}
    3.15  
    3.16      def __init__(self):
    3.17 -        self.dbroot = None
    3.18          self.config_path = None
    3.19          self.config = None
    3.20          self.logging = None
    3.21 @@ -171,7 +167,6 @@ class XendRoot:
    3.22      def configure(self):
    3.23          self.set_config()
    3.24          self.configure_logger()
    3.25 -        self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
    3.26  
    3.27      def configure_logger(self):
    3.28          logfile = self.get_config_value("logfile", self.logfile_default)
    3.29 @@ -192,11 +187,6 @@ class XendRoot:
    3.30          """
    3.31          return self.logging and self.logging.getLogger()
    3.32  
    3.33 -    def get_dbroot(self):
    3.34 -        """Get the path to the database root.
    3.35 -        """
    3.36 -        return self.dbroot
    3.37 -
    3.38      def set_config(self):
    3.39          """If the config file exists, read it. If not, ignore it.
    3.40  
     4.1 --- a/tools/python/xen/xend/XendVnet.py	Thu Jun 09 09:00:58 2005 +0000
     4.2 +++ b/tools/python/xen/xend/XendVnet.py	Thu Jun 09 09:01:57 2005 +0000
     4.3 @@ -4,11 +4,10 @@
     4.4  """
     4.5  
     4.6  from xen.util import Brctl
     4.7 -
     4.8 -import sxp
     4.9 -import XendDB
    4.10 -from XendError import XendError
    4.11 -from XendLogging import log
    4.12 +from xen.xend import sxp
    4.13 +from xen.xend.XendError import XendError
    4.14 +from xen.xend.XendLogging import log
    4.15 +from xen.xend.xenstore import XenNode, DBMap
    4.16  
    4.17  def vnet_cmd(cmd):
    4.18      out = None
    4.19 @@ -63,14 +62,15 @@ class XendVnet:
    4.20      """Index of all vnets. Singleton.
    4.21      """
    4.22  
    4.23 -    dbpath = "vnet"
    4.24 +    dbpath = "/vnet"
    4.25  
    4.26      def __init__(self):
    4.27          # Table of vnet info indexed by vnet id.
    4.28          self.vnet = {}
    4.29 -        self.db = XendDB.XendDB(self.dbpath)
    4.30 -        vnets = self.db.fetchall("")
    4.31 -        for config in vnets.values():
    4.32 +        self.dbmap = DBMap(db=XenNode(self.dbpath))
    4.33 +        self.dbmap.readDB()
    4.34 +        for vnetdb in self.dbmap.values():
    4.35 +            config = vnetdb.config
    4.36              info = XendVnetInfo(config)
    4.37              self.vnet[info.id] = info
    4.38              try:
    4.39 @@ -115,7 +115,7 @@ class XendVnet:
    4.40          """
    4.41          info = XendVnetInfo(config)
    4.42          self.vnet[info.id] = info
    4.43 -        self.db.save(info.id, info.sxpr())
    4.44 +        self.dbmap["%s/config" % info.id] = info.sxpr()
    4.45          info.configure()
    4.46  
    4.47      def vnet_delete(self, id):
    4.48 @@ -126,7 +126,7 @@ class XendVnet:
    4.49          info = self.vnet_get(id)
    4.50          if info:
    4.51              del self.vnet[id]
    4.52 -            self.db.delete(id)
    4.53 +            self.dbmap.delete(id)
    4.54              info.delete()
    4.55  
    4.56  def instance():
     5.1 --- a/tools/python/xen/xend/image.py	Thu Jun 09 09:00:58 2005 +0000
     5.2 +++ b/tools/python/xen/xend/image.py	Thu Jun 09 09:01:57 2005 +0000
     5.3 @@ -4,7 +4,7 @@ import xen.lowlevel.xc; xc = xen.lowleve
     5.4  from xen.xend import sxp
     5.5  from xen.xend.XendError import VmError
     5.6  from xen.xend.XendLogging import log
     5.7 -#from xen.xend.xenstore import DBVar
     5.8 +from xen.xend.xenstore import DBVar
     5.9  
    5.10  class ImageHandler:
    5.11      """Abstract base class for image handlers.
    5.12 @@ -73,7 +73,7 @@ class ImageHandler:
    5.13      #======================================================================
    5.14      # Instance vars and methods.
    5.15  
    5.16 -    #db = None
    5.17 +    db = None
    5.18      ostype = None
    5.19  
    5.20      config = None
    5.21 @@ -82,25 +82,25 @@ class ImageHandler:
    5.22      cmdline = None
    5.23      flags = 0
    5.24  
    5.25 -    #__exports__ = [
    5.26 -    #    DBVar('ostype',  ty='str'),
    5.27 -    #    DBVar('config',  ty='sxpr'),
    5.28 -    #    DBVar('kernel',  ty='str'),
    5.29 -    #    DBVar('ramdisk', ty='str'),
    5.30 -    #    DBVar('cmdline', ty='str'),
    5.31 -    #    DBVar('flags',   ty='int'),
    5.32 -    #    ]
    5.33 +    __exports__ = [
    5.34 +        DBVar('ostype',  ty='str'),
    5.35 +        DBVar('config',  ty='sxpr'),
    5.36 +        DBVar('kernel',  ty='str'),
    5.37 +        DBVar('ramdisk', ty='str'),
    5.38 +        DBVar('cmdline', ty='str'),
    5.39 +        DBVar('flags',   ty='int'),
    5.40 +        ]
    5.41  
    5.42      def __init__(self, vm, config):
    5.43          self.vm = vm
    5.44 -        #self.db = vm.db.addChild('/image')
    5.45 +        self.db = vm.db.addChild('/image')
    5.46          self.config = config
    5.47  
    5.48 -    #def exportToDB(self, save=False):
    5.49 -    #    self.db.exportToDB(self, fields=self.__exports__, save=save)
    5.50 +    def exportToDB(self, save=False):
    5.51 +        self.db.exportToDB(self, fields=self.__exports__, save=save)
    5.52  
    5.53 -    #def importFromDB(self):
    5.54 -    #    self.db.importFromDB(self, fields=self.__exports__)
    5.55 +    def importFromDB(self):
    5.56 +        self.db.importFromDB(self, fields=self.__exports__)
    5.57  
    5.58      def unlink(self, f):
    5.59          if not f: return
    5.60 @@ -234,11 +234,11 @@ class Plan9ImageHandler(ImageHandler):
    5.61  
    5.62  class VmxImageHandler(ImageHandler):
    5.63  
    5.64 -    #__exports__ = ImageHandler.__exports__ + [
    5.65 -    #    DBVar('memmap',        ty='str'),
    5.66 -    #    DBVar('memmap_value',  ty='sxpr'),
    5.67 -    #    # device channel?
    5.68 -    #    ]
    5.69 +    __exports__ = ImageHandler.__exports__ + [
    5.70 +        DBVar('memmap',        ty='str'),
    5.71 +        DBVar('memmap_value',  ty='sxpr'),
    5.72 +        # device channel?
    5.73 +        ]
    5.74      
    5.75      ostype = "vmx"
    5.76      memmap = None
     6.1 --- a/tools/python/xen/xend/server/blkif.py	Thu Jun 09 09:00:58 2005 +0000
     6.2 +++ b/tools/python/xen/xend/server/blkif.py	Thu Jun 09 09:01:57 2005 +0000
     6.3 @@ -9,6 +9,7 @@ from xen.xend.XendRoot import get_compon
     6.4  from xen.xend.XendLogging import log
     6.5  from xen.xend import sxp
     6.6  from xen.xend import Blkctl
     6.7 +from xen.xend.xenstore import DBVar
     6.8  
     6.9  from xen.xend.server import channel
    6.10  from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
    6.11 @@ -158,6 +159,18 @@ class BlkDev(Dev):
    6.12      """Info record for a block device.
    6.13      """
    6.14  
    6.15 +    __exports__ = Dev.__exports__ + [
    6.16 +        DBVar('dev',          ty='str'),
    6.17 +        DBVar('vdev',         ty='int'),
    6.18 +        DBVar('mode',         ty='str'),
    6.19 +        DBVar('viftype',      ty='str'),
    6.20 +        DBVar('params',       ty='str'),
    6.21 +        DBVar('node',         ty='str'),
    6.22 +        DBVar('device',       ty='long'),
    6.23 +        DBVar('start_sector', ty='long'),
    6.24 +        DBVar('nr_sectors',   ty='long'),
    6.25 +        ]
    6.26 +
    6.27      def __init__(self, controller, id, config, recreate=False):
    6.28          Dev.__init__(self, controller, id, config, recreate=recreate)
    6.29          self.dev = None
    6.30 @@ -215,8 +228,7 @@ class BlkDev(Dev):
    6.31  
    6.32      def attach(self, recreate=False, change=False):
    6.33          if recreate:
    6.34 -            node = sxp.child_value(recreate, 'node')
    6.35 -            self.setNode(node)
    6.36 +            pass
    6.37          else:
    6.38              node = Blkctl.block('bind', self.type, self.params)
    6.39              self.setNode(node)
    6.40 @@ -299,7 +311,8 @@ class BlkDev(Dev):
    6.41          return self.controller.getBackend(self.backendDomain)
    6.42  
    6.43      def refresh(self):
    6.44 -        log.debug("Refreshing vbd domain=%d id=%s", self.frontendDomain, self.id)
    6.45 +        log.debug("Refreshing vbd domain=%d id=%s", self.frontendDomain,
    6.46 +                  self.id)
    6.47          self.interfaceChanged()
    6.48  
    6.49      def destroy(self, change=False, reboot=False):
    6.50 @@ -308,7 +321,8 @@ class BlkDev(Dev):
    6.51          @param change: change flag
    6.52          """
    6.53          self.destroyed = True
    6.54 -        log.debug("Destroying vbd domain=%d id=%s", self.frontendDomain, self.id)
    6.55 +        log.debug("Destroying vbd domain=%d id=%s", self.frontendDomain,
    6.56 +                  self.id)
    6.57          self.send_be_vbd_destroy()
    6.58          if change:
    6.59              self.interfaceChanged()
    6.60 @@ -445,5 +459,4 @@ class BlkifController(DevController):
    6.61                  log.error("Exception connecting backend: %s", ex)
    6.62          else:
    6.63              log.error('interface connect on unknown interface: id=%d', id)
    6.64 -    
    6.65  
     7.1 --- a/tools/python/xen/xend/server/channel.py	Thu Jun 09 09:00:58 2005 +0000
     7.2 +++ b/tools/python/xen/xend/server/channel.py	Thu Jun 09 09:01:57 2005 +0000
     7.3 @@ -31,6 +31,33 @@ class EventChannel(dict):
     7.4  
     7.5      interdomain = classmethod(interdomain)
     7.6  
     7.7 +    def restoreFromDB(cls, db, dom1, dom2, port1=0, port2=0):
     7.8 +        """Create an event channel using db info if available.
     7.9 +        Inverse to saveToDB().
    7.10 +
    7.11 +        @param db db
    7.12 +        @param dom1
    7.13 +        @param dom2
    7.14 +        @param port1
    7.15 +        @param port2
    7.16 +        """
    7.17 +        try:
    7.18 +            dom1  = int(db['dom1'])
    7.19 +        except: pass
    7.20 +        try:
    7.21 +            dom2  = int(db['dom2'])
    7.22 +        except: pass
    7.23 +        try:
    7.24 +            port1 = int(db['port1'])
    7.25 +        except: pass
    7.26 +        try:
    7.27 +            port2 = int(db['port2'])
    7.28 +        except: pass
    7.29 +        evtchn = cls.interdomain(dom1, dom2, port1=port1, port2=port2)
    7.30 +        return evtchn
    7.31 +
    7.32 +    restoreFromDB = classmethod(restoreFromDB)
    7.33 +
    7.34      def __init__(self, dom1, dom2, d):
    7.35          d['dom1'] = dom1
    7.36          d['dom2'] = dom2
    7.37 @@ -54,6 +81,18 @@ class EventChannel(dict):
    7.38          evtchn_close(self.dom1, self.port1)
    7.39          evtchn_close(self.dom2, self.port2)
    7.40  
    7.41 +    def saveToDB(self, db):
    7.42 +        """Save the event channel to the db so it can be restored later,
    7.43 +        using restoreFromDB() on the class.
    7.44 +
    7.45 +        @param db db
    7.46 +        """
    7.47 +        db['dom1']  = str(self.dom1)
    7.48 +        db['dom2']  = str(self.dom2)
    7.49 +        db['port1'] = str(self.port1)
    7.50 +        db['port2'] = str(self.port2)
    7.51 +        db.saveDB()
    7.52 +
    7.53      def sxpr(self):
    7.54          return ['event-channel',
    7.55                  ['dom1',  self.dom1  ],
    7.56 @@ -63,7 +102,7 @@ class EventChannel(dict):
    7.57                  ]
    7.58  
    7.59      def __repr__(self):
    7.60 -        return ("<EventChannel dom1:%s:%s dom2:%s:%s>"
    7.61 +        return ("<EventChannel dom1:%d:%d dom2:%d:%d>"
    7.62                  % (self.dom1, self.port1, self.dom2, self.port2))
    7.63  
    7.64  def eventChannel(dom1, dom2, port1=0, port2=0):
    7.65 @@ -241,8 +280,31 @@ class ChannelFactory:
    7.66          @type  remote: int
    7.67          @return: port object
    7.68          """
    7.69 -        return xu.port(dom, local_port=int(local_port),
    7.70 -                       remote_port=int(remote_port))
    7.71 +        return xu.port(dom, local_port=local_port, remote_port=remote_port)
    7.72 +
    7.73 +    def restoreFromDB(self, db, dom, local, remote):
    7.74 +        """Create a channel using ports restored from the db (if available).
    7.75 +        Otherwise use the given ports. This is the inverse operation to
    7.76 +        saveToDB() on a channel.
    7.77 +
    7.78 +        @param db db
    7.79 +        @param dom  domain the channel connects to
    7.80 +        @param local default local port
    7.81 +        @param remote default remote port
    7.82 +        """
    7.83 +        try:
    7.84 +            local_port  = int(db['local_port'])
    7.85 +        except:
    7.86 +            local_port = local
    7.87 +        try:
    7.88 +            remote_port = int(db['remote_port'])
    7.89 +        except:
    7.90 +            remote_port = remote
    7.91 +        try:
    7.92 +            chan = self.openChannel(dom, local_port, remote_port)
    7.93 +        except:
    7.94 +            return None
    7.95 +        return chan
    7.96  
    7.97  def channelFactory():
    7.98      """Singleton constructor for the channel factory.
    7.99 @@ -277,6 +339,17 @@ class Channel:
   7.100          # Make sure the port will deliver all the messages.
   7.101          self.port.register(TYPE_WILDCARD)
   7.102  
   7.103 +    def saveToDB(self, db):
   7.104 +        """Save the channel ports to the db so the channel can be restored later,
   7.105 +        using restoreFromDB() on the factory.
   7.106 +
   7.107 +        @param db db
   7.108 +        """
   7.109 +        if self.closed: return
   7.110 +        db['local_port'] = str(self.getLocalPort())
   7.111 +        db['remote_port'] = str(self.getRemotePort())
   7.112 +        db.saveDB()
   7.113 +
   7.114      def getKey(self):
   7.115          """Get the channel key.
   7.116          """
     8.1 --- a/tools/python/xen/xend/server/console.py	Thu Jun 09 09:00:58 2005 +0000
     8.2 +++ b/tools/python/xen/xend/server/console.py	Thu Jun 09 09:01:57 2005 +0000
     8.3 @@ -13,6 +13,7 @@ from xen.xend import EventServer; eserve
     8.4  from xen.xend.XendLogging import log
     8.5  from xen.xend import XendRoot; xroot = XendRoot.instance()
     8.6  from xen.xend import sxp
     8.7 +from xen.xend.xenstore import DBVar
     8.8  
     8.9  from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
    8.10  from xen.xend.server.messages import *
    8.11 @@ -76,6 +77,12 @@ class ConsoleDev(Dev, protocol.ServerFac
    8.12      STATUS_CONNECTED = 'connected'
    8.13      STATUS_LISTENING = 'listening'
    8.14  
    8.15 +    __exports__ = Dev.__exports__ + [
    8.16 +        DBVar('status',       ty='str'),
    8.17 +        #DBVar('listening',    ty='str'),
    8.18 +        DBVar('console_port', ty='int'),
    8.19 +        ]
    8.20 +
    8.21      def __init__(self, controller, id, config, recreate=False):
    8.22          Dev.__init__(self, controller, id, config)
    8.23          self.lock = threading.RLock()
     9.1 --- a/tools/python/xen/xend/server/controller.py	Thu Jun 09 09:00:58 2005 +0000
     9.2 +++ b/tools/python/xen/xend/server/controller.py	Thu Jun 09 09:01:57 2005 +0000
     9.3 @@ -4,6 +4,7 @@ for a domain.
     9.4  """
     9.5  
     9.6  from xen.xend.XendError import XendError
     9.7 +from xen.xend.xenstore import DBVar
     9.8  from xen.xend.server.messages import msgTypeName, printMsg, getMessageType
     9.9  
    9.10  DEBUG = 0
    9.11 @@ -155,11 +156,16 @@ class DevController:
    9.12  
    9.13      """
    9.14  
    9.15 +    # State:
    9.16 +    # controller/<type> : for controller
    9.17 +    # device/<type>/<id>   : for each device
    9.18 +
    9.19      def createDevController(cls, vm, recreate=False):
    9.20          """Class method to create a dev controller.
    9.21          """
    9.22          ctrl = cls(vm, recreate=recreate)
    9.23          ctrl.initController(recreate=recreate)
    9.24 +        ctrl.exportToDB()
    9.25          return ctrl
    9.26  
    9.27      createDevController = classmethod(createDevController)
    9.28 @@ -169,16 +175,38 @@ class DevController:
    9.29  
    9.30      getType = classmethod(getType)
    9.31  
    9.32 +    __exports__ = [
    9.33 +        DBVar('type',      'str'),
    9.34 +        DBVar('destroyed', 'bool'),
    9.35 +        ]
    9.36 +
    9.37      # Set when registered.
    9.38      type = None
    9.39  
    9.40      def __init__(self, vm, recreate=False):
    9.41          self.destroyed = False
    9.42          self.vm = vm
    9.43 +        self.db = self.getDB()
    9.44          self.deviceId = 0
    9.45          self.devices = {}
    9.46          self.device_order = []
    9.47  
    9.48 +    def getDB(self):
    9.49 +        """Get the db node to use for a controller.
    9.50 +        """
    9.51 +        return self.vm.db.addChild("/controller/%s" % self.getType())
    9.52 +
    9.53 +    def getDevDB(self, id):
    9.54 +        """Get the db node to use for a device.
    9.55 +        """
    9.56 +        return self.vm.db.addChild("/device/%s/%s" % (self.getType(), id))
    9.57 +
    9.58 +    def exportToDB(self, save=False):
    9.59 +        self.db.exportToDB(self, fields=self.__exports__, save=save)
    9.60 +
    9.61 +    def importFromDB(self):
    9.62 +        self.db.importFromDB(self, fields=self.__exports__)
    9.63 +
    9.64      def getDevControllerType(self):
    9.65          return self.dctype
    9.66  
    9.67 @@ -229,15 +257,15 @@ class DevController:
    9.68          If change is true the device is a change to an existing domain,
    9.69          i.e. it is being added at runtime rather than when the domain is created.
    9.70          """
    9.71 -        # skanky hack: we use the device ids to maybe find the savedinfo
    9.72 -        # of the device...
    9.73 -        id = self.nextDeviceId()
    9.74 -        if recreate:
    9.75 -            recreate = self.vm.get_device_savedinfo(self.getType(), id)
    9.76 -        dev = self.newDevice(id, config, recreate=recreate)
    9.77 +        dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate)
    9.78 +        if self.vm.recreate:
    9.79 +            dev.importFromDB()
    9.80          dev.init(recreate=recreate)
    9.81          self.addDevice(dev)
    9.82 +        if not recreate:
    9.83 +            dev.exportToDB()
    9.84          dev.attach(recreate=recreate, change=change)
    9.85 +        dev.exportToDB()
    9.86  
    9.87      def configureDevice(self, id, config, change=False):
    9.88          """Reconfigure an existing device.
    9.89 @@ -344,11 +372,42 @@ class Dev:
    9.90      @type controller: DevController
    9.91      """
    9.92      
    9.93 +    # ./status       : need 2: actual and requested?
    9.94 +    # down-down: initial.
    9.95 +    # up-up: fully up.
    9.96 +    # down-up: down requested, still up. Watch front and back, when both
    9.97 +    # down go to down-down. But what if one (or both) is not connected?
    9.98 +    # Still have front/back trees with status? Watch front/status, back/status?
    9.99 +    # up-down: up requested, still down.
   9.100 +    # Back-end watches ./status, front/status
   9.101 +    # Front-end watches ./status, back/status
   9.102 +    # i.e. each watches the other 2.
   9.103 +    # Each is status/request status/actual?
   9.104 +    #
   9.105 +    # backend?
   9.106 +    # frontend?
   9.107 +
   9.108 +    __exports__ = [
   9.109 +        DBVar('id',        ty='int'),
   9.110 +        DBVar('type',      ty='str'),
   9.111 +        DBVar('config',    ty='sxpr'),
   9.112 +        DBVar('destroyed', ty='bool'),
   9.113 +        ]
   9.114 +
   9.115      def __init__(self, controller, id, config, recreate=False):
   9.116          self.controller = controller
   9.117          self.id = id
   9.118          self.config = config
   9.119          self.destroyed = False
   9.120 +        self.type = self.getType()
   9.121 +
   9.122 +        self.db = controller.getDevDB(id)
   9.123 +
   9.124 +    def exportToDB(self, save=False):
   9.125 +        self.db.exportToDB(self, fields=self.__exports__, save=save)
   9.126 +
   9.127 +    def importFromDB(self):
   9.128 +        self.db.importFromDB(self, fields=self.__exports__)
   9.129  
   9.130      def getDomain(self):
   9.131          return self.controller.getDomain()
    10.1 --- a/tools/python/xen/xend/server/netif.py	Thu Jun 09 09:00:58 2005 +0000
    10.2 +++ b/tools/python/xen/xend/server/netif.py	Thu Jun 09 09:01:57 2005 +0000
    10.3 @@ -12,6 +12,7 @@ from xen.xend.XendError import XendError
    10.4  from xen.xend.XendLogging import log
    10.5  from xen.xend import XendVnet
    10.6  from xen.xend.XendRoot import get_component
    10.7 +from xen.xend.xenstore import DBVar
    10.8  
    10.9  from xen.xend.server import channel
   10.10  from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
   10.11 @@ -21,6 +22,57 @@ class NetDev(Dev):
   10.12      """A network device.
   10.13      """
   10.14  
   10.15 +    # State:
   10.16 +    # inherited + 
   10.17 +    # ./config
   10.18 +    # ./mac
   10.19 +    # ./be_mac
   10.20 +    # ./bridge
   10.21 +    # ./script
   10.22 +    # ./ipaddr ?
   10.23 +    #
   10.24 +    # ./credit
   10.25 +    # ./period
   10.26 +    #
   10.27 +    # ./vifctl: up/down?
   10.28 +    # ./vifname
   10.29 +    #
   10.30 +    #
   10.31 +    # Poss should have no backend state here - except for ref to backend's own tree
   10.32 +    # for the device? And a status - the one we want.
   10.33 +    # ./back/dom
   10.34 +    # ./back/devid - id for back-end (netif_handle) - same as front/devid
   10.35 +    # ./back/id    - backend id (if more than one b/e per domain)
   10.36 +    # ./back/status
   10.37 +    # ./back/tx_shmem_frame  - actually these belong in back-end state
   10.38 +    # ./back/rx_shmem_frame
   10.39 +    #
   10.40 +    # ./front/dom
   10.41 +    # ./front/devid
   10.42 +    # ./front/status - need 2: one for requested, one for actual? Or drive from dev status
   10.43 +    # and this is front status only.
   10.44 +    # ./front/tx_shmem_frame
   10.45 +    # ./front/rx_shmem_frame
   10.46 +    #
   10.47 +    # ./evtchn/front - here or in front/back?
   10.48 +    # ./evtchn/back
   10.49 +    # ./evtchn/status ?
   10.50 +    # At present created by dev: but should be created unbound by front/back
   10.51 +    # separately and then bound (by back)?
   10.52 +
   10.53 +    __exports__ = Dev.__exports__ + [
   10.54 +        DBVar('config',  ty='sxpr'),
   10.55 +        DBVar('mac',     ty='mac'),
   10.56 +        DBVar('be_mac',  ty='mac'),
   10.57 +        DBVar('bridge',  ty='str'),
   10.58 +        DBVar('script',  ty='str'),
   10.59 +        #DBVar('ipaddr'),
   10.60 +        DBVar('credit',  ty='int'),
   10.61 +        DBVar('period',  ty='int'),
   10.62 +        DBVar('vifname', ty='str'),
   10.63 +        DBVar('evtchn'),                #todo: export fields (renamed)
   10.64 +        ]
   10.65 +
   10.66      def __init__(self, controller, id, config, recreate=False):
   10.67          Dev.__init__(self, controller, id, config, recreate=recreate)
   10.68          self.vif = int(self.id)
    11.1 --- a/tools/python/xen/xend/server/usbif.py	Thu Jun 09 09:00:58 2005 +0000
    11.2 +++ b/tools/python/xen/xend/server/usbif.py	Thu Jun 09 09:01:57 2005 +0000
    11.3 @@ -7,6 +7,7 @@
    11.4  from xen.xend import sxp
    11.5  from xen.xend.XendLogging import log
    11.6  from xen.xend.XendError import XendError
    11.7 +from xen.xend.xenstore import DBVar
    11.8  
    11.9  from xen.xend.server import channel
   11.10  from xen.xend.server.controller import Dev, DevController
   11.11 @@ -141,6 +142,11 @@ class UsbBackend:
   11.12  
   11.13  
   11.14  class UsbDev(Dev):
   11.15 +
   11.16 +    __exports__ = Dev.__exports__ + [
   11.17 +        DBVar('port', ty='int'),
   11.18 +        DBVar('path', ty='str'),
   11.19 +        ]
   11.20      
   11.21      def __init__(self, controller, id, config, recreate=False):
   11.22          Dev.__init__(self, controller, id, config, recreate=recreate)
    12.1 --- a/tools/python/xen/xend/xenstore/xsobj.py	Thu Jun 09 09:00:58 2005 +0000
    12.2 +++ b/tools/python/xen/xend/xenstore/xsobj.py	Thu Jun 09 09:01:57 2005 +0000
    12.3 @@ -201,7 +201,10 @@ class DBVar:
    12.4          setAttr(o, self.attr, val)
    12.5  
    12.6      def getDB(self, db):
    12.7 -        data = getattr(db, self.path)
    12.8 +        try:
    12.9 +            data = getattr(db, self.path)
   12.10 +        except AttributeError:
   12.11 +            return None
   12.12          return DBConverter.convertFromDB(data, ty=self.ty)
   12.13  
   12.14      def setDB(self, db, val):