ia64/xen-unstable

changeset 6959:adbe7d45472b

Revert accidental commit.

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