ia64/xen-unstable

changeset 6957:951c8ee275b7

Use DevController.allocateDeviceID rather than using a local variable.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Mon Sep 19 13:41:41 2005 +0100 (2005-09-19)
parents 8f9dfc5fb51c
children db4a0526d4e5
files tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py tools/python/xen/xend/server/netif.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomain.py	Sun Sep 18 22:42:02 2005 +0100
     1.2 +++ b/tools/python/xen/xend/XendDomain.py	Mon Sep 19 13:41:41 2005 +0100
     1.3 @@ -275,8 +275,7 @@ class XendDomain:
     1.4          @param config: configuration
     1.5          @return: domain
     1.6          """
     1.7 -        dominfo = XendDomainInfo.create(self.dbmap, config)
     1.8 -        return dominfo
     1.9 +        return XendDomainInfo.create(self.dbmap.getPath(), config)
    1.10  
    1.11      def domain_restart(self, dominfo):
    1.12          """Restart a domain.
    1.13 @@ -309,8 +308,7 @@ class XendDomain:
    1.14          @param vmconfig: vm configuration
    1.15          """
    1.16          config = sxp.child_value(vmconfig, 'config')
    1.17 -        dominfo = XendDomainInfo.restore(self.dbmap, config)
    1.18 -        return dominfo
    1.19 +        return XendDomainInfo.restore(self.dbmap.getPath(), config)
    1.20  
    1.21      def domain_restore(self, src, progress=False):
    1.22          """Restore a domain from file.
    1.23 @@ -352,13 +350,12 @@ class XendDomain:
    1.24              dompath = self.domroot
    1.25          log.info("Creating entry for unknown xend domain: id=%d uuid=%s",
    1.26                   dom0, uuid)
    1.27 -        db = self.dbmap.addChild("%s/xend" % uuid)
    1.28          try:
    1.29 -            dominfo = XendDomainInfo.recreate(uuid, dompath, dom0,
    1.30 -                                              db, info)
    1.31 -        except:
    1.32 -            raise XendError("Error recreating xend domain info: id=%d" %
    1.33 -                            dom0)
    1.34 +            dominfo = XendDomainInfo.recreate(uuid, dompath, info)
    1.35 +        except Exception, exn:
    1.36 +            log.exception(exn)
    1.37 +            raise XendError("Error recreating xend domain info: id=%d: %s" %
    1.38 +                            (dom0, str(exn)))
    1.39          self._add_domain(dominfo)
    1.40          return dominfo
    1.41          
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Sun Sep 18 22:42:02 2005 +0100
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Sep 19 13:41:41 2005 +0100
     2.3 @@ -136,123 +136,179 @@ class XendDomainInfo:
     2.4      """
     2.5      MINIMUM_RESTART_TIME = 20
     2.6  
     2.7 -    def create(cls, parentdb, config):
     2.8 +
     2.9 +    def create(cls, parentdbpath, config):
    2.10          """Create a VM from a configuration.
    2.11  
    2.12 -        @param parentdb:  parent db
    2.13 +        @param parentdbpath:  parent db path
    2.14          @param config    configuration
    2.15          @raise: VmError for invalid configuration
    2.16          """
    2.17 -        uuid = getUuid()
    2.18 -        db = parentdb.addChild("%s/xend" % uuid)
    2.19 -        path = parentdb.getPath()
    2.20 -        vm = cls(uuid, path, db)
    2.21 -        vm.construct(config)
    2.22 -        vm.saveToDB(sync=True)
    2.23  
    2.24 +        log.debug("XendDomainInfo.create(%s, ...)", parentdbpath)
    2.25 +        
    2.26 +        vm = cls(getUuid(), parentdbpath, cls.parseConfig(config))
    2.27 +        vm.construct()
    2.28          return vm
    2.29  
    2.30      create = classmethod(create)
    2.31  
    2.32 -    def recreate(cls, uuid, path, domid, db, info):
    2.33 +
    2.34 +    def recreate(cls, uuid, dompath, info):
    2.35          """Create the VM object for an existing domain.
    2.36  
    2.37 -        @param db:        domain db
    2.38 +        @param dompath:   The path to all domain information
    2.39          @param info:      domain info from xc
    2.40          """
    2.41 -        vm = cls(uuid, path, db)
    2.42 -        vm.setDomid(domid)
    2.43 -        vm.name, vm.start_time = vm.gatherVm(("name", str),
    2.44 -                                             ("start-time", float))
    2.45 -        try:
    2.46 -            db.readDB()
    2.47 -        except: pass
    2.48 -        vm.importFromDB()
    2.49 -        config = vm.config
    2.50 -        log.debug('info=' + str(info))
    2.51 -        log.debug('config=' + prettyprintstring(config))
    2.52 +
    2.53 +        log.debug("XendDomainInfo.recreate(%s, %s, ...)", uuid, dompath)
    2.54 +
    2.55 +        # ??? vm.setDomid(domid)
    2.56 +#        vm.name, vm.start_time = vm.gatherVm(("name", str),
    2.57 +#                                             ("start-time", float))
    2.58 +#        config = vm.config
    2.59 +#        log.debug('info=' + str(info))
    2.60 +#        log.debug('config=' + prettyprintstring(config))
    2.61 +
    2.62 +#        vm.memory = info['mem_kb'] / 1024
    2.63 +#        vm.target = info['mem_kb'] * 1024
    2.64  
    2.65 -        vm.memory = info['mem_kb'] / 1024
    2.66 -        vm.target = info['mem_kb'] * 1024
    2.67  
    2.68 +        # Parse the configuration in the store, but allow the info we've
    2.69 +        # been given (from xc) to override it.
    2.70 +        path = "%s/%s" % (dompath, uuid)
    2.71 +        
    2.72 +        config = xstransact.Read(path, 'config')
    2.73          if config:
    2.74 -            try:
    2.75 -                vm.recreate = True
    2.76 -                vm.construct(config)
    2.77 -            finally:
    2.78 -                vm.recreate = False
    2.79 -        else:
    2.80 -            vm.setName("Domain-%d" % domid)
    2.81 -
    2.82 -        vm.exportToDB(save=True)
    2.83 -        return vm
    2.84 +            temp_info = cls.parseConfig(config)
    2.85 +            temp_info.update(info)
    2.86 +            info = temp_info
    2.87 +            
    2.88 +        return cls(uuid, dompath, info)
    2.89  
    2.90      recreate = classmethod(recreate)
    2.91  
    2.92 -    def restore(cls, parentdb, config, uuid=None):
    2.93 +
    2.94 +    def restore(cls, parentdbpath, config, uuid = None):
    2.95          """Create a domain and a VM object to do a restore.
    2.96  
    2.97 -        @param parentdb:  parent db
    2.98 +        @param parentdbpath:  parent db
    2.99          @param config:    domain configuration
   2.100          @param uuid:      uuid to use
   2.101          """
   2.102 +        
   2.103 +        log.debug("XendDomainInfo.restore(%s, ..., %s)", parentdbpath, uuid)
   2.104 +
   2.105          if not uuid:
   2.106              uuid = getUuid()
   2.107 -        db = parentdb.addChild("%s/xend" % uuid)
   2.108 -        path = parentdb.getPath()
   2.109 -        vm = cls(uuid, path, db)
   2.110 -        ssidref = int(sxp.child_value(config, 'ssidref'))
   2.111 -        log.debug('restoring with ssidref='+str(ssidref))
   2.112 -        id = xc.domain_create(ssidref = ssidref)
   2.113 -        vm.setDomid(id)
   2.114 +
   2.115 +        try:
   2.116 +            ssidref = int(sxp.child_value(config, 'ssidref'))
   2.117 +        except TypeError, exn:
   2.118 +            raise VmError('Invalid ssidref in config: %s' % exn)
   2.119 +
   2.120 +        log.debug('restoring with ssidref = %d' % ssidref)
   2.121 +
   2.122 +        vm = cls(uuid, parentdbpath, cls.parseConfig(config),
   2.123 +                 xc.domain_create(ssidref = ssidref))
   2.124          vm.clear_shutdown()
   2.125 -        try:
   2.126 -            vm.restore = True
   2.127 -            vm.construct(config)
   2.128 -        finally:
   2.129 -            vm.restore = False
   2.130 -        vm.exportToDB(save=True, sync=True)
   2.131          return vm
   2.132  
   2.133      restore = classmethod(restore)
   2.134  
   2.135 -    __exports__ = [
   2.136 -        DBVar('config',        ty='sxpr'),
   2.137 -        DBVar('state',         ty='str'),
   2.138 -        DBVar('restart_mode',  ty='str'),
   2.139 -        DBVar('restart_state', ty='str'),
   2.140 -        DBVar('restart_time',  ty='float'),
   2.141 -        DBVar('restart_count', ty='int'),
   2.142 -        ]
   2.143 -    
   2.144 -    def __init__(self, uuid, path, db):
   2.145 -        self.uuid = uuid
   2.146 -        self.path = path + "/" + uuid
   2.147 +
   2.148 +    def parseConfig(cls, config):
   2.149 +        def get_cfg(name, default = None):
   2.150 +            return sxp.child_value(config, name, default)
   2.151 +
   2.152 +        def int_get_cfg(name):
   2.153 +            val = get_cfg(name)
   2.154 +            if val:
   2.155 +                return int(val)
   2.156 +            else:
   2.157 +                return None
   2.158 +
   2.159 +        def flo_get_cfg(name):
   2.160 +            val = get_cfg(name)
   2.161 +            if val:
   2.162 +                return float(val)
   2.163 +            else:
   2.164 +                return None
   2.165 +
   2.166 +
   2.167 +        log.debug("parseConfig: config is %s" % str(config))
   2.168 +
   2.169 +
   2.170 +        result = {}
   2.171 +        imagecfg = "()"
   2.172 +        try:
   2.173 +            result['name']         =     get_cfg('name')
   2.174 +            result['ssidref']      = int_get_cfg('ssidref')
   2.175 +            result['memory']       = int_get_cfg('memory')
   2.176 +            result['maxmem']       = int_get_cfg('maxmem')
   2.177 +            result['cpu']          = int_get_cfg('cpu')
   2.178 +            result['cpu_weight']   = flo_get_cfg('cpu_weight')
   2.179 +            result['bootloader']   =     get_cfg('bootloader')
   2.180 +            result['restart_mode'] =     get_cfg('restart')
   2.181 +
   2.182 +            imagecfg = get_cfg('image')
   2.183 +
   2.184 +            if imagecfg:
   2.185 +                result['image'] = imagecfg
   2.186 +                result['vcpus'] = int(sxp.child_value(imagecfg, 'vcpus', 1))
   2.187 +            else:
   2.188 +                result['vcpus'] = 1
   2.189  
   2.190 -        self.db = db
   2.191 +            result['backend'] = []
   2.192 +            for c in sxp.children(config, 'backend'):
   2.193 +                result['backend'].append(sxp.name(sxp.child0(c)))
   2.194 +
   2.195 +            result['device'] = []
   2.196 +            for d in sxp.children(config, 'device'):
   2.197 +                c = sxp.child0(d)
   2.198 +                result['device'].append((sxp.name(c), c))
   2.199 +
   2.200 +
   2.201 +            log.debug("parseConfig: result is %s" % str(result))
   2.202 +            return result
   2.203  
   2.204 -        self.recreate = 0
   2.205 -        self.restore = 0
   2.206 -        
   2.207 -        self.config = None
   2.208 -        self.domid = None
   2.209 -        self.cpu_weight = 1
   2.210 +        except TypeError, exn:
   2.211 +            raise VmError(
   2.212 +                'Invalid ssidref / memory / cpu / cpu_weight / vcpus value: %s %s %s %s %s: %s' %
   2.213 +                (get_cfg('ssidref'),
   2.214 +                 get_cfg('memory'),
   2.215 +                 get_cfg('cpu'),
   2.216 +                 get_cfg('cpu_weight'),
   2.217 +                 sxp.child_value(imagecfg, 'vcpus', 1),
   2.218 +                 str(exn)))
   2.219 +
   2.220 +    parseConfig = classmethod(parseConfig)
   2.221 +
   2.222 +    
   2.223 +    def __init__(self, uuid, parentpath, info, domid = None):
   2.224 +
   2.225 +        self.uuid = uuid
   2.226 +        self.info = info
   2.227 +
   2.228 +        self.path = parentpath + "/" + uuid
   2.229 +
   2.230 +        if domid:
   2.231 +            self.domid = domid
   2.232 +        elif 'dom' in info:
   2.233 +            self.domid = int(info['dom'])
   2.234 +        else:
   2.235 +            self.domid = None
   2.236 +
   2.237 +        self.validateInfo()
   2.238 +
   2.239          self.start_time = None
   2.240 -        self.name = None
   2.241 -        self.memory = None
   2.242 -        self.ssidref = None
   2.243          self.image = None
   2.244  
   2.245 -        self.target = None
   2.246 -
   2.247          self.store_channel = None
   2.248          self.store_mfn = None
   2.249          self.console_channel = None
   2.250          self.console_mfn = None
   2.251          
   2.252 -        self.info = None
   2.253 -        self.backend_flags = 0
   2.254 -        
   2.255          #todo: state: running, suspended
   2.256          self.state = STATE_VM_OK
   2.257          self.state_updated = threading.Condition()
   2.258 @@ -261,17 +317,69 @@ class XendDomainInfo:
   2.259          #todo: set to migrate info if migrating
   2.260          self.migrate = None
   2.261          
   2.262 -        self.restart_mode = RESTART_ONREBOOT
   2.263          self.restart_state = None
   2.264          self.restart_time = None
   2.265          self.restart_count = 0
   2.266          
   2.267 -        self.vcpus = 1
   2.268 -        self.bootloader = None
   2.269 +        self.device_model_pid = 0
   2.270  
   2.271          self.writeVm("uuid", self.uuid)
   2.272          self.storeDom("vm", self.path)
   2.273  
   2.274 +
   2.275 +    def validateInfo(self):
   2.276 +        """Validate and normalise the info block.  This has either been parsed
   2.277 +        by parseConfig, or received from xc through recreate.
   2.278 +        """
   2.279 +        def defaultInfo(name, val):
   2.280 +            if name not in self.info or self.info[name] is None:
   2.281 +                self.info[name] = val()
   2.282 +
   2.283 +    
   2.284 +        try:
   2.285 +            defaultInfo('name',         lambda: "Domain-%d" % self.domid)
   2.286 +            defaultInfo('memory',       lambda: self.info['mem_kb'] / 1024)
   2.287 +            defaultInfo('maxmem',       lambda: self.info['memory'])
   2.288 +            defaultInfo('restart_mode', lambda: RESTART_ONREBOOT)
   2.289 +            defaultInfo('cpu_weight',   lambda: 1.0)
   2.290 +            defaultInfo('bootloader',   lambda: None)
   2.291 +            defaultInfo('backend',      lambda: [])
   2.292 +            defaultInfo('device',       lambda: [])
   2.293 +
   2.294 +            #        vm.target = info['mem_kb'] * 1024
   2.295 +
   2.296 +            # !!! Consistency checks have the possibility of going wrong if
   2.297 +            # xen updates us with a setting which should stay consistent with
   2.298 +            # another.  We should be storing only one value instead.
   2.299 +
   2.300 +            # Validate the given backend names.
   2.301 +            for s in self.info['backend']:
   2.302 +                if s not in backendFlags:
   2.303 +                    raise VmError('Invalid backend type: %s' % s)
   2.304 +
   2.305 +            for (n, c) in self.info['device']:
   2.306 +                if not n or not c or n not in controllerClasses:
   2.307 +                    raise VmError('invalid device (%s, %s)' %
   2.308 +                                  (str(n), str(c)))
   2.309 +
   2.310 +            if self.info['restart_mode'] not in restart_modes:
   2.311 +                raise VmError('invalid restart mode: ' +
   2.312 +                              str(self.info['restart_mode']))
   2.313 +
   2.314 +            if self.info['memory'] <= 0:
   2.315 +                # !!! memory / mem_kb consistency check
   2.316 +                raise VmError('Invalid memory size: %d', self.info['memory'])
   2.317 +
   2.318 +            if 'cpumap' not in self.info:
   2.319 +                if [self.info['vcpus'] == 1]:
   2.320 +                    self.info['cpumap'] = [1];
   2.321 +                else:
   2.322 +                    raise VmError('Cannot create CPU map')
   2.323 +
   2.324 +        except KeyError, exn:
   2.325 +            raise VmError('Unspecified domain detail: %s' % str(exn))
   2.326 +
   2.327 +
   2.328      def readVm(self, *args):
   2.329          return xstransact.Read(self.path, *args)
   2.330  
   2.331 @@ -302,18 +410,27 @@ class XendDomainInfo:
   2.332      def storeDom(self, *args):
   2.333          return xstransact.Store(self.path, *args)
   2.334  
   2.335 -    def setDB(self, db):
   2.336 -        self.db = db
   2.337  
   2.338 -    def saveToDB(self, save=False, sync=False):
   2.339 -        self.db.saveDB(save=save, sync=sync)
   2.340 +    def exportToDB(self, save=False):
   2.341 +        to_store = {
   2.342 +            'id':               str(self.domid),
   2.343 +            'uuid':             self.uuid,
   2.344 +            'config':           sxp.to_string(self.sxpr()),
   2.345  
   2.346 -    def exportToDB(self, save=False, sync=False):
   2.347 -        self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
   2.348 +            'start_time':       str(self.start_time),
   2.349 +            'state':            self.state,
   2.350 +            'restart_time':     str(self.restart_time),
   2.351 +            'restart_count':    str(self.restart_count),
   2.352 +            'device_model_pid': str(self.device_model_pid)
   2.353 +            }
   2.354  
   2.355 -    def importFromDB(self):
   2.356 -        self.db.importFromDB(self, fields=self.__exports__)
   2.357 -        self.store_channel = self.eventChannel("store/port")
   2.358 +        for (k, v) in self.info.items():
   2.359 +            to_store[k] = str(v)
   2.360 +
   2.361 +        log.debug("Storing %s" % str(to_store))
   2.362 +
   2.363 +        self.writeVm(to_store)
   2.364 +
   2.365  
   2.366      def setDomid(self, domid):
   2.367          """Set the domain id.
   2.368 @@ -327,11 +444,11 @@ class XendDomainInfo:
   2.369          return self.domid
   2.370  
   2.371      def setName(self, name):
   2.372 -        self.name = name
   2.373 +        self.info['name'] = name
   2.374          self.storeVm("name", name)
   2.375  
   2.376      def getName(self):
   2.377 -        return self.name
   2.378 +        return self.info['name']
   2.379  
   2.380      def getPath(self):
   2.381          return self.path
   2.382 @@ -340,14 +457,14 @@ class XendDomainInfo:
   2.383          return self.uuid
   2.384  
   2.385      def getVCpuCount(self):
   2.386 -        return self.vcpus
   2.387 +        return self.info['vcpus']
   2.388  
   2.389      def getSsidref(self):
   2.390 -        return self.ssidref
   2.391 +        return self.info['ssidref']
   2.392  
   2.393      def getMemoryTarget(self):
   2.394          """Get this domain's target memory size, in MiB."""
   2.395 -        return self.memory
   2.396 +        return self.info['memory']
   2.397  
   2.398      def setStoreRef(self, ref):
   2.399          self.store_mfn = ref
   2.400 @@ -355,7 +472,8 @@ class XendDomainInfo:
   2.401  
   2.402  
   2.403      def getBackendFlags(self):
   2.404 -        return self.backend_flags
   2.405 +        return reduce(lambda x, y: x | backendFlags[y],
   2.406 +                      self.info['backend'], 0)
   2.407  
   2.408  
   2.409      def closeStoreChannel(self):
   2.410 @@ -379,18 +497,19 @@ class XendDomainInfo:
   2.411      def setMemoryTarget(self, target):
   2.412          self.storeDom("memory/target", target)
   2.413  
   2.414 -    def update(self, info=None):
   2.415 -        """Update with  info from xc.domain_getinfo().
   2.416 +
   2.417 +    def update(self, info = None):
   2.418 +        """Update with info from xc.domain_getinfo().
   2.419          """
   2.420 -        if info:
   2.421 -            self.info = info
   2.422 -        else:
   2.423 -            di = dom_get(self.domid)
   2.424 -            if not di:
   2.425 +
   2.426 +        if not info:
   2.427 +            info = dom_get(self.domid)
   2.428 +            if not info:
   2.429                  return
   2.430 -            self.info = di 
   2.431 -        self.memory = self.info['mem_kb'] / 1024
   2.432 -        self.ssidref = self.info['ssidref']
   2.433 +            
   2.434 +        self.info.update(info)
   2.435 +        self.validateInfo()
   2.436 +
   2.437  
   2.438      def state_set(self, state):
   2.439          self.state_updated.acquire()
   2.440 @@ -398,7 +517,7 @@ class XendDomainInfo:
   2.441              self.state = state
   2.442              self.state_updated.notifyAll()
   2.443          self.state_updated.release()
   2.444 -        self.saveToDB()
   2.445 +        self.exportToDB()
   2.446  
   2.447      def state_wait(self, state):
   2.448          self.state_updated.acquire()
   2.449 @@ -409,9 +528,9 @@ class XendDomainInfo:
   2.450      def __str__(self):
   2.451          s = "<domain"
   2.452          s += " id=" + str(self.domid)
   2.453 -        s += " name=" + self.name
   2.454 -        s += " memory=" + str(self.memory)
   2.455 -        s += " ssidref=" + str(self.ssidref)
   2.456 +        s += " name=" + self.info['name']
   2.457 +        s += " memory=" + str(self.info['memory'])
   2.458 +        s += " ssidref=" + str(self.info['ssidref'])
   2.459          s += ">"
   2.460          return s
   2.461  
   2.462 @@ -441,32 +560,43 @@ class XendDomainInfo:
   2.463      def sxpr(self):
   2.464          sxpr = ['domain',
   2.465                  ['domid', self.domid],
   2.466 -                ['name', self.name],
   2.467 -                ['memory', self.memory],
   2.468 -                ['ssidref', self.ssidref],
   2.469 -                ['target', self.target] ]
   2.470 +                ['name', self.info['name']],
   2.471 +                ['memory', self.info['memory']],
   2.472 +                ['ssidref', self.info['ssidref']]]
   2.473 +#        ,                ['target', self.target] ]
   2.474          if self.uuid:
   2.475              sxpr.append(['uuid', self.uuid])
   2.476          if self.info:
   2.477 -            sxpr.append(['maxmem', self.info['maxmem_kb']/1024 ])
   2.478 -            run   = (self.info['running']  and 'r') or '-'
   2.479 -            block = (self.info['blocked']  and 'b') or '-'
   2.480 -            pause = (self.info['paused']   and 'p') or '-'
   2.481 -            shut  = (self.info['shutdown'] and 's') or '-'
   2.482 -            crash = (self.info['crashed']  and 'c') or '-'
   2.483 -            state = run + block + pause + shut + crash
   2.484 +            sxpr.append(['maxmem', self.info['maxmem']])
   2.485 +
   2.486 +            def stateChar(name):
   2.487 +                if name in self.info:
   2.488 +                    if self.info[name]:
   2.489 +                        return name[0]
   2.490 +                    else:
   2.491 +                        return '-'
   2.492 +                else:
   2.493 +                    return '?'
   2.494 +
   2.495 +            state = reduce(
   2.496 +                lambda x, y: x + y,
   2.497 +                map(stateChar,
   2.498 +                    ['running', 'blocked', 'paused', 'shutdown', 'crashed']))
   2.499 +
   2.500              sxpr.append(['state', state])
   2.501 -            if self.info['shutdown']:
   2.502 +            if 'shutdown' in self.info and self.info['shutdown']:
   2.503                  reason = shutdown_reason(self.info['shutdown_reason'])
   2.504                  sxpr.append(['shutdown_reason', reason])
   2.505 -            sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]])
   2.506 -            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])    
   2.507 +            if 'cpu_time' in self.info:
   2.508 +                sxpr.append(['cpu_time', self.info['cpu_time']/1e9])    
   2.509              sxpr.append(['vcpus', self.info['vcpus']])
   2.510              sxpr.append(['cpumap', self.info['cpumap']])
   2.511 -            # build a string, using '|' to seperate items, show only up
   2.512 -            # to number of vcpus in domain, and trim the trailing '|'
   2.513 -            sxpr.append(['vcpu_to_cpu', ''.join(map(lambda x: str(x)+'|',
   2.514 -                        self.info['vcpu_to_cpu'][0:self.info['vcpus']]))[:-1]])
   2.515 +            if 'vcpu_to_cpu' in self.info:
   2.516 +                sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]])
   2.517 +                # build a string, using '|' to separate items, show only up
   2.518 +                # to number of vcpus in domain, and trim the trailing '|'
   2.519 +                sxpr.append(['vcpu_to_cpu', ''.join(map(lambda x: str(x)+'|',
   2.520 +                            self.info['vcpu_to_cpu'][0:self.info['vcpus']]))[:-1]])
   2.521              
   2.522          if self.start_time:
   2.523              up_time =  time.time() - self.start_time  
   2.524 @@ -492,8 +622,8 @@ class XendDomainInfo:
   2.525              sxpr.append(['restart_state', self.restart_state])
   2.526          if self.restart_time:
   2.527              sxpr.append(['restart_time', str(self.restart_time)])
   2.528 -        if self.config:
   2.529 -            sxpr.append(['config', self.config])
   2.530 +#        if self.config:
   2.531 +#            sxpr.append(['config', self.config])
   2.532          return sxpr
   2.533  
   2.534      def check_name(self, name):
   2.535 @@ -504,7 +634,6 @@ class XendDomainInfo:
   2.536          @param name: name
   2.537          @raise: VMerror if invalid
   2.538          """
   2.539 -        if self.recreate: return
   2.540          if name is None or name == '':
   2.541              raise VmError('missing vm name')
   2.542          for c in name:
   2.543 @@ -523,26 +652,49 @@ class XendDomainInfo:
   2.544          if not self.domid or (dominfo.domid != self.domid):
   2.545              raise VmError('vm name clash: ' + name)
   2.546          
   2.547 -    def construct(self, config):
   2.548 +    def construct(self):
   2.549          """Construct the vm instance from its configuration.
   2.550  
   2.551          @param config: configuration
   2.552          @raise: VmError on error
   2.553          """
   2.554          # todo - add support for scheduling params?
   2.555 -        self.config = config
   2.556          try:
   2.557              # Initial domain create.
   2.558 -            self.setName(sxp.child_value(config, 'name'))
   2.559 -            self.check_name(self.name)
   2.560 -            self.init_image()
   2.561 -            self.configure_cpus(config)
   2.562 -            self.init_domain()
   2.563 +            self.check_name(self.info['name'])
   2.564 +            self.setName(self.info['name'])
   2.565 +
   2.566 +            if 'image' not in self.info:
   2.567 +                raise VmError('Missing image in configuration')
   2.568 +
   2.569 +            self.image = ImageHandler.create(self, self.info['image'])
   2.570 +
   2.571 +            self.setMemoryTarget(self.info['memory'] * (1 << 20))
   2.572 +
   2.573 +            log.error('%s %s %s %s %s',
   2.574 +                      str(self.domid),
   2.575 +                      str(self.info['memory']),
   2.576 +                      str(self.info['ssidref']),
   2.577 +                      str(self.info['cpu']),
   2.578 +                      str(self.info['cpu_weight']))
   2.579 +
   2.580 +            self.setDomid(self.image.initDomain(self.domid,
   2.581 +                                                self.info['memory'],
   2.582 +                                                self.info['ssidref'],
   2.583 +                                                self.info['cpu'],
   2.584 +                                                self.info['cpu_weight'],
   2.585 +                                                self.info['bootloader']))
   2.586 +            
   2.587 +            if self.start_time is None:
   2.588 +                self.start_time = time.time()
   2.589 +                self.storeVm(("start-time", self.start_time))
   2.590 +
   2.591 +            log.debug('init_domain> Created domain=%d name=%s memory=%d',
   2.592 +                      self.domid, self.info['name'], self.info['memory'])
   2.593 +
   2.594              self.register_domain()
   2.595  
   2.596              # Create domain devices.
   2.597 -            self.configure_backends()
   2.598 -            self.configure_restart()
   2.599              self.construct_image()
   2.600              self.configure()
   2.601              self.exportToDB(save=True)
   2.602 @@ -559,41 +711,12 @@ class XendDomainInfo:
   2.603          xd._add_domain(self)
   2.604          self.exportToDB(save=True)
   2.605  
   2.606 -    def configure_cpus(self, config):
   2.607 -        try:
   2.608 -            self.cpu_weight = float(sxp.child_value(config, 'cpu_weight', '1'))
   2.609 -        except:
   2.610 -            raise VmError('invalid cpu weight')
   2.611 -        self.memory = int(sxp.child_value(config, 'memory'))
   2.612 -        if self.memory is None:
   2.613 -            raise VmError('missing memory size')
   2.614 -        self.setMemoryTarget(self.memory * (1 << 20))
   2.615 -        self.ssidref = int(sxp.child_value(config, 'ssidref'))
   2.616 -        cpu = sxp.child_value(config, 'cpu')
   2.617 -        if self.recreate and self.domid and cpu is not None and int(cpu) >= 0:
   2.618 -            xc.domain_pincpu(self.domid, 0, 1<<int(cpu))
   2.619 -        try:
   2.620 -            image = sxp.child_value(self.config, 'image')
   2.621 -            vcpus = sxp.child_value(image, 'vcpus')
   2.622 -            if vcpus:
   2.623 -                self.vcpus = int(vcpus)
   2.624 -        except:
   2.625 -            raise VmError('invalid vcpus value')
   2.626 -
   2.627      def configure_vcpus(self, vcpus):
   2.628          d = {}
   2.629          for v in range(0, vcpus):
   2.630              d["cpu/%d/availability" % v] = "online"
   2.631          self.writeVm(d)
   2.632  
   2.633 -    def init_image(self):
   2.634 -        """Create boot image handler for the domain.
   2.635 -        """
   2.636 -        image = sxp.child_value(self.config, 'image')
   2.637 -        if image is None:
   2.638 -            raise VmError('missing image')
   2.639 -        self.image = ImageHandler.create(self, image)
   2.640 -
   2.641      def construct_image(self):
   2.642          """Construct the boot image for the domain.
   2.643          """
   2.644 @@ -604,21 +727,17 @@ class XendDomainInfo:
   2.645              IntroduceDomain(self.domid, self.store_mfn,
   2.646                              self.store_channel.port1, self.path)
   2.647          # get the configured value of vcpus and update store
   2.648 -        self.configure_vcpus(self.vcpus)
   2.649 +        self.configure_vcpus(self.info['vcpus'])
   2.650 +
   2.651  
   2.652      def delete(self):
   2.653          """Delete the vm's db.
   2.654          """
   2.655 -        self.domid = None
   2.656 -        self.saveToDB(sync=True)
   2.657          try:
   2.658 -            # Todo: eventually will have to wait for devices to signal
   2.659 -            # destruction before can delete the db.
   2.660 -            if self.db:
   2.661 -                self.db.delete()
   2.662 +            xstransact.Remove(self.path, 'id')
   2.663          except Exception, ex:
   2.664              log.warning("error in domain db delete: %s", ex)
   2.665 -            pass
   2.666 +
   2.667  
   2.668      def destroy_domain(self):
   2.669          """Destroy the vm's domain.
   2.670 @@ -630,7 +749,7 @@ class XendDomainInfo:
   2.671          try:
   2.672              xc.domain_destroy(dom=self.domid)
   2.673          except Exception, err:
   2.674 -            log.exception("Domain destroy failed: %s", self.name)
   2.675 +            log.exception("Domain destroy failed: %s", self.info['name'])
   2.676  
   2.677      def cleanup(self):
   2.678          """Cleanup vm resources: release devices.
   2.679 @@ -653,11 +772,14 @@ class XendDomainInfo:
   2.680                  pass
   2.681  
   2.682      def destroy(self):
   2.683 -        """Clenup vm and destroy domain.
   2.684 +        """Cleanup vm and destroy domain.
   2.685          """
   2.686 +
   2.687 +        log.debug("XendDomainInfo.destroy")
   2.688 +
   2.689          self.destroy_domain()
   2.690          self.cleanup()
   2.691 -        self.saveToDB()
   2.692 +        self.exportToDB()
   2.693          return 0
   2.694  
   2.695      def is_terminated(self):
   2.696 @@ -670,6 +792,7 @@ class XendDomainInfo:
   2.697          """
   2.698  
   2.699          t = xstransact("%s/device" % self.path)
   2.700 +
   2.701          for n in controllerClasses.keys():
   2.702              for d in t.list(n):
   2.703                  try:
   2.704 @@ -686,28 +809,11 @@ class XendDomainInfo:
   2.705      def show(self):
   2.706          """Print virtual machine info.
   2.707          """
   2.708 -        print "[VM dom=%d name=%s memory=%d ssidref=%d" % (self.domid, self.name, self.memory, self.ssidref)
   2.709 +        print "[VM dom=%d name=%s memory=%d ssidref=%d" % (self.domid, self.info['name'], self.info['memory'], self.info['ssidref'])
   2.710          print "image:"
   2.711          sxp.show(self.image)
   2.712          print "]"
   2.713  
   2.714 -    def init_domain(self):
   2.715 -        """Initialize the domain memory.
   2.716 -        """
   2.717 -        if self.recreate:
   2.718 -            return
   2.719 -        if self.start_time is None:
   2.720 -            self.start_time = time.time()
   2.721 -            self.storeVm(("start-time", self.start_time))
   2.722 -        try:
   2.723 -            cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
   2.724 -        except:
   2.725 -            raise VmError('invalid cpu')
   2.726 -        id = self.image.initDomain(self.domid, self.memory, self.ssidref, cpu, self.cpu_weight)
   2.727 -        log.debug('init_domain> Created domain=%d name=%s memory=%d',
   2.728 -                  id, self.name, self.memory)
   2.729 -        self.setDomid(id)
   2.730 -
   2.731      def eventChannel(self, path=None):
   2.732          """Create an event channel to the domain.
   2.733          
   2.734 @@ -731,14 +837,8 @@ class XendDomainInfo:
   2.735          self.console_channel = self.eventChannel("console/port")
   2.736  
   2.737      def create_configured_devices(self):
   2.738 -        devices = sxp.children(self.config, 'device')
   2.739 -        for d in devices:
   2.740 -            dev_config = sxp.child0(d)
   2.741 -            if dev_config is None:
   2.742 -                raise VmError('invalid device')
   2.743 -            dev_type = sxp.name(dev_config)
   2.744 -
   2.745 -            self.createDevice(dev_type, dev_config)
   2.746 +        for (n, c) in self.info['device']:
   2.747 +            self.createDevice(n, c)
   2.748  
   2.749  
   2.750      def create_devices(self):
   2.751 @@ -770,14 +870,6 @@ class XendDomainInfo:
   2.752          self.configureDevice(deviceClass, devid, dev_config)
   2.753  
   2.754  
   2.755 -    def configure_restart(self):
   2.756 -        """Configure the vm restart mode.
   2.757 -        """
   2.758 -        r = sxp.child_value(self.config, 'restart', RESTART_ONREBOOT)
   2.759 -        if r not in restart_modes:
   2.760 -            raise VmError('invalid restart mode: ' + str(r))
   2.761 -        self.restart_mode = r;
   2.762 -
   2.763      def restart_needed(self, reason):
   2.764          """Determine if the vm needs to be restarted when shutdown
   2.765          for the given reason.
   2.766 @@ -785,11 +877,11 @@ class XendDomainInfo:
   2.767          @param reason: shutdown reason
   2.768          @return True if needs restart, False otherwise
   2.769          """
   2.770 -        if self.restart_mode == RESTART_NEVER:
   2.771 +        if self.info['restart_mode'] == RESTART_NEVER:
   2.772              return False
   2.773 -        if self.restart_mode == RESTART_ALWAYS:
   2.774 +        if self.info['restart_mode'] == RESTART_ALWAYS:
   2.775              return True
   2.776 -        if self.restart_mode == RESTART_ONREBOOT:
   2.777 +        if self.info['restart_mode'] == RESTART_ONREBOOT:
   2.778              return reason == 'reboot'
   2.779          return False
   2.780  
   2.781 @@ -821,7 +913,7 @@ class XendDomainInfo:
   2.782              tdelta = tnow - self.restart_time
   2.783              if tdelta < self.MINIMUM_RESTART_TIME:
   2.784                  self.restart_cancel()
   2.785 -                msg = 'VM %s restarting too fast' % self.name
   2.786 +                msg = 'VM %s restarting too fast' % self.info['name']
   2.787                  log.error(msg)
   2.788                  raise VmError(msg)
   2.789          self.restart_time = tnow
   2.790 @@ -840,14 +932,13 @@ class XendDomainInfo:
   2.791              self.exportToDB()
   2.792              self.restart_state = STATE_RESTART_BOOTING
   2.793              self.configure_bootloader()
   2.794 -            self.construct(self.config)
   2.795 -            self.saveToDB()
   2.796 +            self.construct()
   2.797 +            self.exportToDB()
   2.798          finally:
   2.799              self.restart_state = None
   2.800  
   2.801      def configure_bootloader(self):
   2.802 -        self.bootloader = sxp.child_value(self.config, "bootloader")
   2.803 -        if not self.bootloader:
   2.804 +        if not self.info['bootloader']:
   2.805              return
   2.806          # if we're restarting with a bootloader, we need to run it
   2.807          # FIXME: this assumes the disk is the first device and
   2.808 @@ -858,30 +949,13 @@ class XendDomainInfo:
   2.809          if dev:
   2.810              disk = sxp.child_value(dev, "uname")
   2.811              fn = blkdev_uname_to_file(disk)
   2.812 -            blcfg = bootloader(self.bootloader, fn, 1, self.vcpus)
   2.813 +            blcfg = bootloader(self.info['bootloader'], fn, 1, self.info['vcpus'])
   2.814          if blcfg is None:
   2.815              msg = "Had a bootloader specified, but can't find disk"
   2.816              log.error(msg)
   2.817              raise VmError(msg)
   2.818          self.config = sxp.merge(['vm', ['image', blcfg]], self.config)
   2.819  
   2.820 -    def configure_backends(self):
   2.821 -        """Set configuration flags if the vm is a backend for netif or blkif.
   2.822 -        Configure the backends to use for vbd and vif if specified.
   2.823 -        """
   2.824 -        for c in sxp.children(self.config, 'backend'):
   2.825 -            v = sxp.child0(c)
   2.826 -            name = sxp.name(v)
   2.827 -            if name == 'blkif':
   2.828 -                self.backend_flags |= SIF_BLK_BE_DOMAIN
   2.829 -            elif name == 'netif':
   2.830 -                self.backend_flags |= SIF_NET_BE_DOMAIN
   2.831 -            elif name == 'usbif':
   2.832 -                pass
   2.833 -            elif name == 'tpmif':
   2.834 -                self.backend_flags |= SIF_TPM_BE_DOMAIN
   2.835 -            else:
   2.836 -                raise VmError('invalid backend type:' + str(name))
   2.837  
   2.838      def configure(self):
   2.839          """Configure a vm.
   2.840 @@ -899,19 +973,16 @@ class XendDomainInfo:
   2.841          """
   2.842          return
   2.843  
   2.844 +
   2.845      def configure_maxmem(self):
   2.846 -        try:
   2.847 -            maxmem = int(sxp.child_value(self.config, 'maxmem', self.memory))
   2.848 -            xc.domain_setmaxmem(self.domid, maxmem_kb = maxmem * 1024)
   2.849 -        except:
   2.850 -            raise VmError("invalid maxmem: " +
   2.851 -                          sxp.child_value(self.config, 'maxmem'))
   2.852 +        xc.domain_setmaxmem(self.domid,
   2.853 +                            maxmem_kb = self.info['maxmem'] * 1024)
   2.854  
   2.855  
   2.856      def vcpu_hotplug(self, vcpu, state):
   2.857          """Disable or enable VCPU in domain.
   2.858          """
   2.859 -        if vcpu > self.vcpus:
   2.860 +        if vcpu > self.info['vcpus']:
   2.861              log.error("Invalid VCPU %d" % vcpu)
   2.862              return
   2.863          if int(state) == 0:
   2.864 @@ -1000,16 +1071,24 @@ implements the device control specific t
   2.865  controllerClasses = {}
   2.866  
   2.867  
   2.868 -def addControllerClass(device_class, cls):
   2.869 +"""A map of backend names and the corresponding flag."""
   2.870 +backendFlags = {}
   2.871 +
   2.872 +
   2.873 +def addControllerClass(device_class, backend_name, backend_flag, cls):
   2.874      """Register a subclass of DevController to handle the named device-class.
   2.875 +
   2.876 +    @param backend_flag One of the SIF_XYZ_BE_DOMAIN constants, or None if
   2.877 +    no flag is to be set.
   2.878      """
   2.879      cls.deviceClass = device_class
   2.880 +    backendFlags[backend_name] = backend_flag
   2.881      controllerClasses[device_class] = cls
   2.882  
   2.883  
   2.884  from xen.xend.server import blkif, netif, tpmif, pciif, usbif
   2.885 -addControllerClass('vbd',  blkif.BlkifController)
   2.886 -addControllerClass('vif',  netif.NetifController)
   2.887 -addControllerClass('vtpm', tpmif.TPMifController)
   2.888 -addControllerClass('pci',  pciif.PciController)
   2.889 -addControllerClass('usb',  usbif.UsbifController)
   2.890 +addControllerClass('vbd',  'blkif', SIF_BLK_BE_DOMAIN, blkif.BlkifController)
   2.891 +addControllerClass('vif',  'netif', SIF_NET_BE_DOMAIN, netif.NetifController)
   2.892 +addControllerClass('vtpm', 'tpmif', SIF_TPM_BE_DOMAIN, tpmif.TPMifController)
   2.893 +addControllerClass('pci',  'pciif', None,              pciif.PciController)
   2.894 +addControllerClass('usb',  'usbif', None,              usbif.UsbifController)
     3.1 --- a/tools/python/xen/xend/image.py	Sun Sep 18 22:42:02 2005 +0100
     3.2 +++ b/tools/python/xen/xend/image.py	Mon Sep 19 13:41:41 2005 +0100
     3.3 @@ -145,22 +145,21 @@ class ImageHandler:
     3.4          except OSError, ex:
     3.5              log.warning("error removing bootloader file '%s': %s", f, ex)
     3.6  
     3.7 -    def initDomain(self, dom, memory, ssidref, cpu, cpu_weight):
     3.8 +    def initDomain(self, dom, memory, ssidref, cpu, cpu_weight, bootloading):
     3.9          """Initial domain create.
    3.10  
    3.11          @return domain id
    3.12          """
    3.13  
    3.14          mem_kb = self.getDomainMemory(memory)
    3.15 -        if not self.vm.restore:
    3.16 -            dom = xc.domain_create(dom = dom or 0, ssidref = ssidref)
    3.17 -            # if bootloader, unlink here. But should go after buildDomain() ?
    3.18 -            if self.vm.bootloader:
    3.19 -                self.unlink(self.kernel)
    3.20 -                self.unlink(self.ramdisk)
    3.21 -            if dom <= 0:
    3.22 -                raise VmError('Creating domain failed: name=%s' %
    3.23 -                              self.vm.getName())
    3.24 +        dom = xc.domain_create(dom = dom or 0, ssidref = ssidref)
    3.25 +        # if bootloader, unlink here. But should go after buildDomain() ?
    3.26 +        if bootloading:
    3.27 +            self.unlink(self.kernel)
    3.28 +            self.unlink(self.ramdisk)
    3.29 +        if dom <= 0:
    3.30 +            raise VmError('Creating domain failed: name=%s' %
    3.31 +                          self.vm.getName())
    3.32          log.debug("initDomain: cpu=%d mem_kb=%d ssidref=%d dom=%d", cpu, mem_kb, ssidref, dom)
    3.33          xc.domain_setcpuweight(dom, cpu_weight)
    3.34          xc.domain_setmaxmem(dom, mem_kb)
    3.35 @@ -184,9 +183,6 @@ class ImageHandler:
    3.36      def createDomain(self):
    3.37          """Build the domain boot image.
    3.38          """
    3.39 -        if self.vm.recreate or self.vm.restore:
    3.40 -            return
    3.41 -
    3.42          # Set params and call buildDomain().
    3.43          self.flags = self.vm.getBackendFlags()
    3.44  
     4.1 --- a/tools/python/xen/xend/server/netif.py	Sun Sep 18 22:42:02 2005 +0100
     4.2 +++ b/tools/python/xen/xend/server/netif.py	Mon Sep 19 13:41:41 2005 +0100
     4.3 @@ -27,9 +27,6 @@ from xen.xend import sxp
     4.4  from xen.xend.server.DevController import DevController
     4.5  
     4.6  
     4.7 -next_devid = 1
     4.8 -
     4.9 -
    4.10  class NetifController(DevController):
    4.11      """Network interface controller. Handles all network devices for a domain.
    4.12      """
    4.13 @@ -41,8 +38,6 @@ class NetifController(DevController):
    4.14      def getDeviceDetails(self, config):
    4.15          """@see DevController.getDeviceDetails"""
    4.16  
    4.17 -        global next_devid
    4.18 -
    4.19          from xen.xend import XendRoot
    4.20          xroot = XendRoot.instance()
    4.21  
    4.22 @@ -52,9 +47,6 @@ class NetifController(DevController):
    4.23                  val.append(sxp.child0(ipaddr))
    4.24              return val
    4.25  
    4.26 -        devid = next_devid
    4.27 -        next_devid += 1
    4.28 -
    4.29          script = os.path.join(xroot.network_script_dir,
    4.30                                sxp.child_value(config, 'script',
    4.31                                                xroot.get_vif_script()))
    4.32 @@ -63,6 +55,8 @@ class NetifController(DevController):
    4.33          mac = sxp.child_value(config, 'mac')
    4.34          ipaddr = _get_config_ipaddr(config)
    4.35  
    4.36 +        devid = self.allocateDeviceID()
    4.37 +
    4.38          back = { 'script' : script,
    4.39                   'mac' : mac,
    4.40                   'bridge' : bridge,