ia64/xen-unstable

changeset 12230:ec7e7e946496

[XEND] Reverting self.domains UUID indexing

Due to localhost migration, it is possible to have two VMs with the
same UUID on the same host. So instead, we revert back to XendDomain
where there are two lists, a "domains" of active domains indexed by
domid and a "managed_domains" which is a list of all domains whose
lifecycle is managed by Xend.

Signed-off-by: Alastair Tse <atse@xensource.com>
author Alastair Tse <atse@xensource.com>
date Thu Nov 02 18:51:23 2006 +0000 (2006-11-02)
parents 96ad1d72fccf
children 20204db0891b
files tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomain.py	Thu Nov 02 15:48:32 2006 +0000
     1.2 +++ b/tools/python/xen/xend/XendDomain.py	Thu Nov 02 18:51:23 2006 +0000
     1.3 @@ -36,6 +36,7 @@ from xen.xend.XendConfig import XendConf
     1.4  from xen.xend.XendError import XendError, XendInvalidDomain
     1.5  from xen.xend.XendLogging import log
     1.6  from xen.xend.XendConstants import XS_VMROOT
     1.7 +from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_RUNNING
     1.8  
     1.9  from xen.xend.xenstore.xstransact import xstransact
    1.10  from xen.xend.xenstore.xswatch import xswatch
    1.11 @@ -69,7 +70,7 @@ class XendDomain:
    1.12  
    1.13      def __init__(self):
    1.14          self.domains = {}
    1.15 -        self.managed_domains = []
    1.16 +        self.managed_domains = {}
    1.17          self.domains_lock = threading.RLock()
    1.18  
    1.19          # xen api instance vars
    1.20 @@ -170,7 +171,6 @@ class XendDomain:
    1.21                      if not running_dom:
    1.22                          # instantiate domain if not started.
    1.23                          new_dom = XendDomainInfo.createDormant(dom)
    1.24 -                        self._add_domain(new_dom)
    1.25                          self._managed_domain_register(new_dom)
    1.26                      else:
    1.27                          self._managed_domain_register(running_dom)
    1.28 @@ -307,31 +307,16 @@ class XendDomain:
    1.29  
    1.30      def _managed_domain_unregister(self, dom):
    1.31          try:
    1.32 -            self.managed_domains.remove((dom.get_uuid(), dom.getName()))
    1.33 +            if self.is_domain_managed(dom):
    1.34 +                del self.managed_domains[dom.get_uuid()]
    1.35          except ValueError:
    1.36              log.warn("Domain is not registered: %s" % dom.get_uuid())
    1.37  
    1.38      def _managed_domain_register(self, dom):
    1.39 -        self.managed_domains.append((dom.get_uuid(), dom.getName()))
    1.40 -
    1.41 -    def _managed_domain_rename(self, dom, new_name):
    1.42 -        for i in range(len(self.managed_domains)):
    1.43 -            if self.managed_domains[i][0] == dom.get_uuid():
    1.44 -                self.managed_domains[i][1] = new_name
    1.45 -                return True
    1.46 -        return False
    1.47 +        self.managed_domains[dom.get_uuid()] = dom
    1.48  
    1.49 -    def is_domain_managed(self, dom = None, dom_name = None):
    1.50 -        dom_uuid = dom.get_uuid()
    1.51 -        dom_name = dom.getName()
    1.52 -        if dom:
    1.53 -            return ((dom_uuid, dom_name) in self.managed_domains)
    1.54 -        if dom_name:
    1.55 -            results = [d for d in self.managed_domains if d[1] == dom_name]
    1.56 -            return (len(results) > 0)
    1.57 -        return False
    1.58 -
    1.59 -    
    1.60 +    def is_domain_managed(self, dom = None):
    1.61 +        return (dom.get_uuid() in self.managed_domains)
    1.62  
    1.63      # End of Managed Domain Access
    1.64      # --------------------------------------------------------------------
    1.65 @@ -376,55 +361,47 @@ class XendDomain:
    1.66              # - like cpu_time, status, dying, etc.
    1.67              running = self._running_domains()
    1.68              for dom in running:
    1.69 -                dom_info = self.domain_lookup_nr(dom['domid'])
    1.70 -                if dom_info:
    1.71 -                    dom_info.update(dom)
    1.72 +                domid = dom['domid']
    1.73 +                if domid in self.domains:
    1.74 +                    self.domains[domid].update(dom)
    1.75  
    1.76 -            # clean up unmanaged domains
    1.77 -            for dom in self.domains.values():
    1.78 -                if (dom.getDomid() == None) and \
    1.79 -                       not self.is_domain_managed(dom):
    1.80 -                    self._remove_domain(dom)
    1.81 +            # remove domains that are not running from active
    1.82 +            # domain list
    1.83 +            running_domids = [d['domid'] for d in running]
    1.84 +            for domid, dom in self.domains.items():
    1.85 +                if domid not in running_domids and domid != DOM0_ID:
    1.86 +                    self._remove_domain(dom, domid)
    1.87                      
    1.88          finally:
    1.89              self.domains_lock.release()
    1.90  
    1.91 -    def _add_domain(self, info, managed = False):
    1.92 +    def _add_domain(self, info):
    1.93          """Add the given domain entry to this instance's internal cache.
    1.94          
    1.95          @requires: Expects to be protected by the domains_lock.
    1.96          @param info: XendDomainInfo of a domain to be added.
    1.97          @type info: XendDomainInfo
    1.98 -        @keyword managed: Whether this domain is maanged by Xend
    1.99 -        @type managed: boolean
   1.100          """
   1.101 -        log.debug("Adding Domain: %s" % info.get_uuid())
   1.102 -        self.domains[info.get_uuid()] = info
   1.103 -        if managed and not self.is_domain_managed(info):
   1.104 -            self._managed_domain_register(info)
   1.105 +        log.debug("Adding Domain: %s" % info.getDomid())
   1.106 +        self.domains[info.getDomid()] = info
   1.107  
   1.108 -    def _remove_domain(self, info):
   1.109 +    def _remove_domain(self, info, domid = None):
   1.110          """Remove the given domain from this instance's internal cache.
   1.111          
   1.112          @requires: Expects to be protected by the domains_lock.
   1.113          @param info: XendDomainInfo of a domain to be removed.
   1.114          @type info: XendDomainInfo
   1.115          """
   1.116 +
   1.117          if info:
   1.118 -            dom_name = info.getName()
   1.119 -            dom_uuid = info.get_uuid()
   1.120 -            
   1.121 -            if info.state != XendDomainInfo.DOM_STATE_HALTED:
   1.122 -                info.cleanupDomain()
   1.123 +            if domid == None:
   1.124 +                domid = info.getDomid()
   1.125  
   1.126 -            if self.is_domain_managed(info):
   1.127 -                self._managed_config_remove(dom_uuid)
   1.128 -                self._managed_domain_unregister(info)
   1.129 -                
   1.130 -            try:
   1.131 -                del self.domains[dom_uuid]
   1.132 -            except KeyError:
   1.133 -                pass
   1.134 +            if info.state != DOM_STATE_HALTED:
   1.135 +                info.cleanupDomain()
   1.136 +            
   1.137 +            if domid in self.domains:
   1.138 +                del self.domains[domid]
   1.139          else:
   1.140              log.warning("Attempted to remove non-existent domain.")
   1.141  
   1.142 @@ -498,11 +475,9 @@ class XendDomain:
   1.143  
   1.144              # lookup by id
   1.145              try:
   1.146 -                match = [d for d in self.domains.values() \
   1.147 -                       if d.getDomid() == int(domid)]
   1.148 -                if match:
   1.149 -                    return match[0]
   1.150 -            except (ValueError, TypeError):
   1.151 +                if int(domid) in self.domains:
   1.152 +                    return self.domains[int(domid)]
   1.153 +            except ValueError:
   1.154                  pass
   1.155  
   1.156              return None
   1.157 @@ -516,7 +491,7 @@ class XendDomain:
   1.158          """
   1.159          self.domains_lock.acquire()
   1.160          try:
   1.161 -            return self.domains[DOM0_UUID]
   1.162 +            return self.domains[DOM0_ID]
   1.163          finally:
   1.164              self.domains_lock.release()
   1.165  
   1.166 @@ -533,7 +508,7 @@ class XendDomain:
   1.167                  if dom.getName() == DOM0_NAME:
   1.168                      continue
   1.169                  
   1.170 -                if dom.state == XendDomainInfo.DOM_STATE_RUNNING:
   1.171 +                if dom.state == DOM_STATE_RUNNING:
   1.172                      shutdownAction = dom.info.get('on_xend_stop', 'ignore')
   1.173                      if shutdownAction == 'shutdown':
   1.174                          log.debug('Shutting down domain: %s' % dom.getName())
   1.175 @@ -561,15 +536,21 @@ class XendDomain:
   1.176          try:
   1.177              self.domains_lock.acquire()
   1.178              result = [d.get_uuid() for d in self.domains.values()]
   1.179 +            result += self.managed_domains.keys()
   1.180 +            return result
   1.181          finally:
   1.182              self.domains_lock.release()
   1.183 -        return result
   1.184  
   1.185      def get_vm_by_uuid(self, vm_uuid):
   1.186          self.domains_lock.acquire()
   1.187          try:
   1.188 -            if vm_uuid in self.domains:
   1.189 -                return self.domains[vm_uuid]
   1.190 +            for dom in self.domains.values():
   1.191 +                if dom.get_uuid() == vm_uuid:
   1.192 +                    return dom
   1.193 +
   1.194 +            if vm_uuid in self.managed_domains:
   1.195 +                return self.managed_domains[vm_uuid]
   1.196 +
   1.197              return None
   1.198          finally:
   1.199              self.domains_lock.release()
   1.200 @@ -577,7 +558,7 @@ class XendDomain:
   1.201      def get_vm_with_dev_uuid(self, klass, dev_uuid):
   1.202          self.domains_lock.acquire()
   1.203          try:
   1.204 -            for dom in self.domains.values():
   1.205 +            for dom in self.domains.values() + self.managed_domains.values():
   1.206                  if dom.has_device(klass, dev_uuid):
   1.207                      return dom
   1.208              return None
   1.209 @@ -607,17 +588,16 @@ class XendDomain:
   1.210      def do_legacy_api_with_uuid(self, fn, vm_uuid, *args):
   1.211          self.domains_lock.acquire()
   1.212          try:
   1.213 -            if vm_uuid in self.domains:
   1.214 -                # problem is domid does not exist for unstarted
   1.215 -                # domains, so in that case, we use the name.
   1.216 -                # TODO: probably want to modify domain_lookup_nr
   1.217 -                #       to lookup uuids, or just ignore
   1.218 -                #       the legacy api and reimplement all these
   1.219 -                #       calls.
   1.220 -                domid = self.domains[vm_uuid].getDomid()
   1.221 +            for domid, dom in self.domains.items():
   1.222 +                if dom.get_uuid == vm_uuid:
   1.223 +                    return fn(domid, *args)
   1.224 +                    
   1.225 +            if vm_uuid in self.managed_domains:
   1.226 +                domid = self.managed_domains[vm_uuid].getDomid()
   1.227                  if domid == None:
   1.228 -                    domid = self.domains[vm_uuid].getName()
   1.229 +                    domid = self.managed_domains[vm_uuid].getName()
   1.230                  return fn(domid, *args)
   1.231 +            
   1.232              raise XendInvalidDomain("Domain does not exist")
   1.233          finally:
   1.234              self.domains_lock.release()
   1.235 @@ -631,7 +611,7 @@ class XendDomain:
   1.236                  dominfo = XendDomainInfo.createDormant(xeninfo)
   1.237                  log.debug("Creating new managed domain: %s: %s" %
   1.238                            (dominfo.getName(), dominfo.get_uuid()))
   1.239 -                self._add_domain(dominfo, managed = True)
   1.240 +                self._managed_domain_register(dominfo)
   1.241                  self.managed_config_save(dominfo)
   1.242                  return dominfo.get_uuid()
   1.243              except XendError, e:
   1.244 @@ -647,9 +627,6 @@ class XendDomain:
   1.245              old_name = dom.getName()
   1.246              dom.setName(new_name)
   1.247  
   1.248 -            if self.is_domain_managed(dom):
   1.249 -                self._managed_domain_rename(dom, new_name)
   1.250 -
   1.251          finally:
   1.252              self.domains_lock.release()
   1.253                  
   1.254 @@ -670,7 +647,18 @@ class XendDomain:
   1.255          self.domains_lock.acquire()
   1.256          try:
   1.257              self._refresh()
   1.258 -            return self.domains.values()
   1.259 +            
   1.260 +            # active domains
   1.261 +            active_domains = self.domains.values()
   1.262 +            active_uuids = [d.get_uuid() for d in active_domains]
   1.263 +
   1.264 +            # inactive domains
   1.265 +            inactive_domains = []
   1.266 +            for dom_uuid, dom in self.managed_domains.items():
   1.267 +                if dom_uuid not in active_uuids:
   1.268 +                    inactive_domains.append(dom)
   1.269 +
   1.270 +            return active_domains + inactive_domains
   1.271          finally:
   1.272              self.domains_lock.release()
   1.273  
   1.274 @@ -710,7 +698,7 @@ class XendDomain:
   1.275              if dominfo.getDomid() == DOM0_ID:
   1.276                  raise XendError("Cannot save privileged domain %s" % domname)
   1.277  
   1.278 -            if dominfo.state != XendDomainInfo.DOM_STATE_RUNNING:
   1.279 +            if dominfo.state != DOM_STATE_RUNNING:
   1.280                  raise XendError("Cannot suspend domain that is not running.")
   1.281  
   1.282              if not os.path.exists(self._managed_config_path(domname)):
   1.283 @@ -745,7 +733,7 @@ class XendDomain:
   1.284              if dominfo.getDomid() == DOM0_ID:
   1.285                  raise XendError("Cannot save privileged domain %s" % domname)
   1.286  
   1.287 -            if dominfo.state != XendDomainInfo.DOM_STATE_HALTED:
   1.288 +            if dominfo.state != DOM_STATE_HALTED:
   1.289                  raise XendError("Cannot suspend domain that is not running.")
   1.290  
   1.291              chkpath = self._managed_check_point_path(domname)
   1.292 @@ -801,7 +789,7 @@ class XendDomain:
   1.293                  dominfo = XendDomainInfo.createDormant(xeninfo)
   1.294                  log.debug("Creating new managed domain: %s" %
   1.295                            dominfo.getName())
   1.296 -                self._add_domain(dominfo, managed = True)
   1.297 +                self._managed_domain_register(dominfo)
   1.298                  self.managed_config_save(dominfo)
   1.299                  # no return value because it isn't meaningful for client
   1.300              except XendError, e:
   1.301 @@ -827,7 +815,7 @@ class XendDomain:
   1.302              if not dominfo:
   1.303                  raise XendInvalidDomain(str(domid))
   1.304  
   1.305 -            if dominfo.state != XendDomainInfo.DOM_STATE_HALTED:
   1.306 +            if dominfo.state != DOM_STATE_HALTED:
   1.307                  raise XendError("Domain is already running")
   1.308              
   1.309              dominfo.start(is_managed = True)
   1.310 @@ -838,7 +826,7 @@ class XendDomain:
   1.311          
   1.312  
   1.313      def domain_delete(self, domid):
   1.314 -        """Remove a domain from database
   1.315 +        """Remove a managed domain from database
   1.316  
   1.317          @require: Domain must not be running.
   1.318          @param domid: Domain name or domain ID.
   1.319 @@ -853,9 +841,10 @@ class XendDomain:
   1.320                  if not dominfo:
   1.321                      raise XendInvalidDomain(str(domid))
   1.322  
   1.323 -                if dominfo.state != XendDomainInfo.DOM_STATE_HALTED:
   1.324 +                if dominfo.state != DOM_STATE_HALTED:
   1.325                      raise XendError("Domain is still running")
   1.326  
   1.327 +                self._managed_domain_unregister(dominfo)
   1.328                  self._remove_domain(dominfo)
   1.329                  
   1.330              except Exception, ex:
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Nov 02 15:48:32 2006 +0000
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Thu Nov 02 18:51:23 2006 +0000
     2.3 @@ -245,7 +245,6 @@ def restore(config):
     2.4      """
     2.5  
     2.6      log.debug("XendDomainInfo.restore(%s)", config)
     2.7 -
     2.8      vm = XendDomainInfo(XendConfig(sxp = config), resume = True)
     2.9      try:
    2.10          vm.resume()
    2.11 @@ -775,7 +774,7 @@ class XendDomainInfo:
    2.12                  "Scheduling refreshShutdown on domain %d in %ds.",
    2.13                  self.domid, timeout)
    2.14              threading.Timer(timeout, self._refreshShutdown).start()
    2.15 -
    2.16 +            
    2.17          return True
    2.18  
    2.19  
    2.20 @@ -849,7 +848,7 @@ class XendDomainInfo:
    2.21          # given reason.  This restart has to be done out of the scope of
    2.22          # refresh_shutdown_lock.
    2.23          restart_reason = None
    2.24 -        
    2.25 +
    2.26          self.refresh_shutdown_lock.acquire()
    2.27          try:
    2.28              if xeninfo is None:
    2.29 @@ -1368,7 +1367,7 @@ class XendDomainInfo:
    2.30      def waitForShutdown(self):
    2.31          self.state_updated.acquire()
    2.32          try:
    2.33 -            while self.state in (DOM_STATE_RUNNING,):
    2.34 +            while self.state in (DOM_STATE_RUNNING,DOM_STATE_PAUSED):
    2.35                  self.state_updated.wait()
    2.36          finally:
    2.37              self.state_updated.release()
    2.38 @@ -1624,7 +1623,6 @@ class XendDomainInfo:
    2.39      def update(self, info = None, refresh = True):
    2.40          """Update with info from xc.domain_getinfo().
    2.41          """
    2.42 -
    2.43          log.trace("XendDomainInfo.update(%s) on domain %s", info,
    2.44                    str(self.domid))
    2.45