ia64/xen-unstable

changeset 1729:3e4c28963eba

bitkeeper revision 1.1060 (40eeb0ebK9z3-bkkK-MRSf1CtEAOOQ)

Support for domain reboot.
author mjw@wray-m-3.hpl.hp.com
date Fri Jul 09 14:51:23 2004 +0000 (2004-07-09)
parents 52fa3846c70b
children 1ff36c572e07
files tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/tools/python/xen/xend/XendDomain.py	Fri Jul 09 12:53:50 2004 +0000
     1.2 +++ b/tools/python/xen/xend/XendDomain.py	Fri Jul 09 14:51:23 2004 +0000
     1.3 @@ -65,10 +65,10 @@ class XendDomain:
     1.4      def schedule_later(self, _delay, _name, _fn, *args):
     1.5          """Schedule a function to be called later (if not already scheduled).
     1.6  
     1.7 -        _delay delay in seconds
     1.8 -        _name  schedule name
     1.9 -        _fn    function
    1.10 -        args   arguments
    1.11 +        @param _delay: delay in seconds
    1.12 +        @param _name:  schedule name
    1.13 +        @param _fn:    function
    1.14 +        @param args:   arguments
    1.15          """
    1.16          if self.schedule.get(_name): return
    1.17          self.schedule[_name] = reactor.callLater(_delay, _fn, *args)
    1.18 @@ -76,7 +76,7 @@ class XendDomain:
    1.19      def schedule_cancel(self, name):
    1.20          """Cancel a scheduled function call.
    1.21          
    1.22 -        name schedule name to cancel
    1.23 +        @param name: schedule name to cancel
    1.24          """
    1.25          callid = self.schedule.get(name)
    1.26          if not callid:
    1.27 @@ -88,7 +88,7 @@ class XendDomain:
    1.28      def reap_schedule(self, delay=0):
    1.29          """Schedule reap to be called later.
    1.30  
    1.31 -        delay delay in seconds
    1.32 +        @param delay: delay in seconds
    1.33          """
    1.34          self.schedule_later(delay, 'reap', self.reap)
    1.35  
    1.36 @@ -100,7 +100,7 @@ class XendDomain:
    1.37      def refresh_schedule(self, delay=0):
    1.38          """Schedule refresh to be called later.
    1.39          
    1.40 -        delay delay in seconds
    1.41 +        @param delay: delay in seconds
    1.42          """
    1.43          self.schedule_later(delay, 'refresh', self.refresh)
    1.44  
    1.45 @@ -109,6 +109,18 @@ class XendDomain:
    1.46          """
    1.47          self.schedule_cancel('refresh')
    1.48  
    1.49 +    def domain_restarts_schedule(self, delay=0):
    1.50 +        """Schedule domain_restarts to be called later.
    1.51 +        
    1.52 +        @param delay: delay in seconds
    1.53 +        """
    1.54 +        self.schedule_later(delay, 'domain_restarts', self.domain_restarts)
    1.55 +        
    1.56 +    def domain_restarts_cancel(self):
    1.57 +        """Cancel any scheduled call of domain_restarts.
    1.58 +        """
    1.59 +        self.schedule_cancel('domain_restarts')
    1.60 +        
    1.61      def rm_all(self):
    1.62          """Remove all domain info. Used after reboot.
    1.63          """
    1.64 @@ -118,7 +130,6 @@ class XendDomain:
    1.65      def initial_refresh(self):
    1.66          """Refresh initial domain info from domain_db.
    1.67          """
    1.68 -        print "initial_refresh>"
    1.69          for d in self.domain_db.values(): print 'db dom=', d
    1.70          domlist = xc.domain_getinfo()
    1.71          for d in domlist: print 'xc dom=', d
    1.72 @@ -164,10 +175,9 @@ class XendDomain:
    1.73      def _new_domain(self, savedinfo, info):
    1.74          """Create a domain entry from saved info.
    1.75  
    1.76 -        savedinfo saved info from the db
    1.77 -        info      domain info from xen
    1.78 -
    1.79 -        returns deferred
    1.80 +        @param savedinfo: saved info from the db
    1.81 +        @param info:      domain info from xen
    1.82 +        @return: deferred
    1.83          """
    1.84          config = sxp.child_value(savedinfo, 'config')
    1.85          deferred = XendDomainInfo.vm_recreate(config, info)
    1.86 @@ -179,9 +189,9 @@ class XendDomain:
    1.87      def _add_domain(self, id, info, notify=1):
    1.88          """Add a domain entry to the tables.
    1.89  
    1.90 -        id     domain id
    1.91 -        info   domain info object
    1.92 -        notify send a domain created event if true
    1.93 +        @param id:     domain id
    1.94 +        @param info:   domain info object
    1.95 +        @param notify: send a domain created event if true
    1.96          """
    1.97          self.domain[id] = info
    1.98          self.domain_db[id] = info.sxpr()
    1.99 @@ -191,8 +201,8 @@ class XendDomain:
   1.100      def _delete_domain(self, id, notify=1):
   1.101          """Remove a domain from the tables.
   1.102  
   1.103 -        id     domain id
   1.104 -        notify send a domain died event if true
   1.105 +        @param id:     domain id
   1.106 +        @param notify: send a domain died event if true
   1.107          """
   1.108          if id in self.domain:
   1.109              if notify: eserver.inject('xend.domain.died', id)
   1.110 @@ -206,7 +216,6 @@ class XendDomain:
   1.111          Tidy them up.
   1.112          """
   1.113          self.reap_cancel()
   1.114 -        print 'XendDomain>reap>'
   1.115          domlist = xc.domain_getinfo()
   1.116          casualties = []
   1.117          for d in domlist:
   1.118 @@ -219,8 +228,14 @@ class XendDomain:
   1.119          for d in casualties:
   1.120              id = str(d['dom'])
   1.121              print 'XendDomain>reap> died id=', id, d
   1.122 +            if d['shutdown']:
   1.123 +                reason = XendDomainInfo.shutdown_reason(d['shutdown_reason'])
   1.124 +                print 'XendDomain>reap> shutdown id=', id, reason
   1.125 +                if reason in ['poweroff', 'reboot']:
   1.126 +                    self.domain_restart_schedule(id, reason)
   1.127              self.final_domain_destroy(id)
   1.128 -        print 'XendDomain>reap<'
   1.129 +        if len(self.restarts):
   1.130 +            self.domain_restarts_schedule()
   1.131  
   1.132      def refresh(self):
   1.133          """Refresh domain list from Xen.
   1.134 @@ -252,7 +267,7 @@ class XendDomain:
   1.135      def refresh_domain(self, id):
   1.136          """Refresh information for a single domain.
   1.137  
   1.138 -        id domain id
   1.139 +        @param id: domain id
   1.140          """
   1.141          dom = int(id)
   1.142          dominfo = xc.domain_getinfo(dom, 1)
   1.143 @@ -271,7 +286,7 @@ class XendDomain:
   1.144      def domain_ls(self):
   1.145          """Get list of domain ids.
   1.146  
   1.147 -        return domain ids
   1.148 +        @return: domain ids
   1.149          """
   1.150          self.refresh()
   1.151          return self.domain.keys()
   1.152 @@ -279,7 +294,7 @@ class XendDomain:
   1.153      def domains(self):
   1.154          """Get list of domain objects.
   1.155  
   1.156 -        return domain objects
   1.157 +        @return: domain objects
   1.158          """
   1.159          self.refresh()
   1.160          return self.domain.values()
   1.161 @@ -287,9 +302,8 @@ class XendDomain:
   1.162      def domain_create(self, config):
   1.163          """Create a domain from a configuration.
   1.164  
   1.165 -        config configuration
   1.166 -
   1.167 -        returns deferred
   1.168 +        @param config: configuration
   1.169 +        @return: deferred
   1.170          """
   1.171          deferred = XendDomainInfo.vm_create(config)
   1.172          def fn(dominfo):
   1.173 @@ -301,8 +315,8 @@ class XendDomain:
   1.174      def domain_get(self, id):
   1.175          """Get up-to-date info about a domain.
   1.176  
   1.177 -        id domain id
   1.178 -        returns domain object (or None)
   1.179 +        @param id: domain id
   1.180 +        @return: domain object (or None)
   1.181          """
   1.182          id = str(id)
   1.183          self.refresh_domain(id)
   1.184 @@ -311,7 +325,7 @@ class XendDomain:
   1.185      def domain_unpause(self, id):
   1.186          """Unpause domain execution.
   1.187  
   1.188 -        id domain id
   1.189 +        @param id: domain id
   1.190          """
   1.191          dom = int(id)
   1.192          eserver.inject('xend.domain.unpause', id)
   1.193 @@ -320,7 +334,7 @@ class XendDomain:
   1.194      def domain_pause(self, id):
   1.195          """Pause domain execution.
   1.196  
   1.197 -        id domain id
   1.198 +        @param id: domain id
   1.199          """
   1.200          dom = int(id)
   1.201          eserver.inject('xend.domain.pause', id)
   1.202 @@ -328,14 +342,20 @@ class XendDomain:
   1.203      
   1.204      def domain_shutdown(self, id, reason='poweroff'):
   1.205          """Shutdown domain (nicely).
   1.206 +         - poweroff: domain will restart if has autorestart set.
   1.207 +         - reboot: domain will restart.
   1.208 +         - halt: domain will not restart (even if has autorestart set).
   1.209  
   1.210 -        id     domain id
   1.211 -        reason shutdown type: poweroff, reboot, suspend, halt
   1.212 +        @param id:     domain id
   1.213 +        @param reason: shutdown type: poweroff, reboot, suspend, halt
   1.214          """
   1.215          dom = int(id)
   1.216          if dom <= 0:
   1.217              return 0
   1.218 -        self.domain_restart_schedule(id, reason)
   1.219 +        if reason == 'halt':
   1.220 +            self.domain_restart_cancel(id)
   1.221 +        else:
   1.222 +            self.domain_restart_schedule(id, reason)
   1.223          eserver.inject('xend.domain.shutdown', [id, reason])
   1.224          if reason == 'halt':
   1.225              reason = 'poweroff'
   1.226 @@ -346,28 +366,30 @@ class XendDomain:
   1.227      def domain_restart_schedule(self, id, reason):
   1.228          """Schedule a restart for a domain if it needs one.
   1.229  
   1.230 -        id     domain id
   1.231 -        reason shutdown reason
   1.232 +        @param id:     domain id
   1.233 +        @param reason: shutdown reason
   1.234          """
   1.235 -        if id in self.restarts:
   1.236 -            # Don't schedule if already there.
   1.237 +        print 'domain_restart_schedule>', id, reason
   1.238 +        dominfo = self.domain.get(id)
   1.239 +        if not dominfo or id in self.restarts:
   1.240 +            # Don't schedule if unknown or already there.
   1.241 +            print 'domain_restart_schedule> no domain'
   1.242              return
   1.243 -        restart = 0
   1.244 -        if reason in ['poweroff', 'reboot']:
   1.245 -            dominfo = self.domain.get(id)
   1.246 -            if dominfo and (dominfo.autorestart or reason == 'reboot'):
   1.247 -                restart = 1
   1.248 -                # Clear autorestart flag to avoid multiple restarts.
   1.249 -                dominfo.autorestart = 0
   1.250 -            
   1.251 +        restart = ((reason == 'reboot') or
   1.252 +                   (reason == 'poweroff' and dominfo.autorestart))
   1.253          if restart:
   1.254 +            # Clear autorestart flag to avoid multiple restarts.
   1.255 +            dominfo.autorestart = 0
   1.256              self.restarts[id] = dominfo.config
   1.257 +            print 'Scheduling restart for domain:', id, dominfo.name
   1.258 +            self.domain_restarts_schedule()
   1.259              
   1.260      def domain_restart_cancel(self, id):
   1.261          """Cancel any restart scheduled for a domain.
   1.262  
   1.263 -        id domain id
   1.264 +        @param id: domain id
   1.265          """
   1.266 +        print 'domain_restart_cancel>', id
   1.267          dominfo = self.domain.get(id)
   1.268          if dominfo:
   1.269              dominfo.autorestart = 0
   1.270 @@ -377,23 +399,36 @@ class XendDomain:
   1.271      def domain_restarts(self):
   1.272          """Execute any scheduled domain restarts for domains that have gone.
   1.273          """
   1.274 +        print 'domain_restarts>'
   1.275 +        self.domain_restarts_cancel()
   1.276          for id in self.restarts.keys():
   1.277              if id in self.domain:
   1.278 +                print 'domain_restarts> still running:', id
   1.279                  # Don't execute restart for domains still running.
   1.280                  continue
   1.281              config = self.restarts[id]
   1.282              # Remove it from the restarts.
   1.283              del self.restarts[id]
   1.284              try:
   1.285 -                self.domain_create(config)
   1.286 +                print 'domain_restarts> restart:', id, config
   1.287 +                def cbok(dominfo):
   1.288 +                    print 'Restarted domain', id, 'as', dominfo.id
   1.289 +                    self.domain_unpause(dominfo.id)
   1.290 +                def cberr(err):
   1.291 +                    print >>sys.stderr, "Delayed exception restarting domain: ", err
   1.292 +                deferred = self.domain_create(config)
   1.293 +                deferred.addCallback(cbok)
   1.294 +                deferred.addCallback(cberr)
   1.295              except:
   1.296                  print >>sys.stderr, "XendDomain> Exception restarting domain"
   1.297                  traceback.print_exc(sys.stderr)
   1.298 +        if len(self.restarts):
   1.299 +            self.refresh_schedule(delay=5)
   1.300          
   1.301      def final_domain_destroy(self, id):
   1.302          """Final destruction of a domain..
   1.303  
   1.304 -        id domain id
   1.305 +        @param id: domain id
   1.306          """
   1.307          dom = int(id)
   1.308          if dom <= 0:
   1.309 @@ -410,7 +445,7 @@ class XendDomain:
   1.310          """Terminate domain immediately.
   1.311          Camcels any restart for the domain.
   1.312  
   1.313 -        id domain id
   1.314 +        @param id: domain id
   1.315          """
   1.316          self.domain_restart_cancel(id)
   1.317          val = self.final_domain_destroy(id)
   1.318 @@ -420,7 +455,7 @@ class XendDomain:
   1.319      def domain_migrate(self, id, dst):
   1.320          """Start domain migration.
   1.321  
   1.322 -        id domain id
   1.323 +        @param id: domain id
   1.324          """
   1.325          # Need a cancel too?
   1.326          # Don't forget to cancel restart for it.
   1.327 @@ -432,9 +467,9 @@ class XendDomain:
   1.328          """Save domain state to file, destroy domain on success.
   1.329          Leave domain running on error.
   1.330  
   1.331 -        id       domain id
   1.332 -        dst      destination file
   1.333 -        progress output progress if true
   1.334 +        @param id:       domain id
   1.335 +        @param dst:      destination file
   1.336 +        @param progress: output progress if true
   1.337          """
   1.338          dom = int(id)
   1.339          dominfo = self.domain_get(id)
   1.340 @@ -457,10 +492,9 @@ class XendDomain:
   1.341      def domain_restore(self, src, progress=0):
   1.342          """Restore domain from file.
   1.343  
   1.344 -        src      source file
   1.345 -        progress output progress if true
   1.346 -
   1.347 -        returns domain object
   1.348 +        @param src :     source file
   1.349 +        @param progress: output progress if true
   1.350 +        @return: domain object
   1.351          """
   1.352          dominfo = XendDomainInfo.vm_restore(src, progress=progress)
   1.353          self._add_domain(dominfo.id, dominfo)
   1.354 @@ -469,8 +503,8 @@ class XendDomain:
   1.355      def domain_pincpu(self, dom, cpu):
   1.356          """Pin a domain to a cpu.
   1.357  
   1.358 -        dom domain
   1.359 -        cpu cpu number
   1.360 +        @param dom: domain
   1.361 +        @param cpu: cpu number
   1.362          """
   1.363          dom = int(dom)
   1.364          return xc.domain_pincpu(dom, cpu)
   1.365 @@ -493,7 +527,7 @@ class XendDomain:
   1.366          """
   1.367          dom = int(dom)
   1.368          return xc.fbvtsched_domain_set(dom=dom, mcuadv=mcuadv,
   1.369 -                                      warp=warp, warpl=warpl, warpu=warpu)
   1.370 +                                       warp=warp, warpl=warpl, warpu=warpu)
   1.371  
   1.372      def domain_cpu_fbvt_get(self, dom):
   1.373          """Get FBVT (Fair Borrowed Virtual Time) scheduler parameters for a domain.
   1.374 @@ -516,10 +550,9 @@ class XendDomain:
   1.375      def domain_devtype_ls(self, dom, type):
   1.376          """Get list of device indexes for a domain.
   1.377  
   1.378 -        dom  domain
   1.379 -        type device type
   1.380 -
   1.381 -        returns device indexes
   1.382 +        @param dom:  domain
   1.383 +        @param type: device type
   1.384 +        @return: device indexes
   1.385          """
   1.386          dominfo = self.domain_get(dom)
   1.387          if not dominfo: return None
   1.388 @@ -529,11 +562,10 @@ class XendDomain:
   1.389      def domain_devtype_get(self, dom, type, idx):
   1.390          """Get a device from a domain.
   1.391  
   1.392 -        dom  domain
   1.393 -        type device type
   1.394 -        idx  device index
   1.395 -
   1.396 -        returns device object (or None)
   1.397 +        @param dom:  domain
   1.398 +        @param type: device type
   1.399 +        @param idx:  device index
   1.400 +        @return: device object (or None)
   1.401          """
   1.402          dominfo = self.domain_get(dom)
   1.403          if not dominfo: return None
   1.404 @@ -542,46 +574,42 @@ class XendDomain:
   1.405      def domain_vif_ls(self, dom):
   1.406          """Get list of virtual network interface (vif) indexes for a domain.
   1.407  
   1.408 -        dom domain
   1.409 -
   1.410 -        returns vif indexes
   1.411 +        @param dom: domain
   1.412 +        @return: vif indexes
   1.413          """
   1.414          return self.domain_devtype_ls(dom, 'vif')
   1.415  
   1.416      def domain_vif_get(self, dom, vif):
   1.417          """Get a virtual network interface (vif) from a domain.
   1.418  
   1.419 -        dom domain
   1.420 -        vif vif index
   1.421 -
   1.422 -        returns vif device object (or None)
   1.423 +        @param dom: domain
   1.424 +        @param vif: vif index
   1.425 +        @return: vif device object (or None)
   1.426          """
   1.427          return self.domain_devtype_get(dom, 'vif', vif)
   1.428  
   1.429      def domain_vbd_ls(self, dom):
   1.430          """Get list of virtual block device (vbd) indexes for a domain.
   1.431  
   1.432 -        dom domain
   1.433 -
   1.434 -        returns vbd indexes
   1.435 +        @param dom: domain
   1.436 +        @return: vbd indexes
   1.437          """
   1.438          return self.domain_devtype_ls(dom, 'vbd')
   1.439  
   1.440      def domain_vbd_get(self, dom, vbd):
   1.441          """Get a virtual block device (vbd) from a domain.
   1.442  
   1.443 -        dom domain
   1.444 -        vbd vbd index
   1.445 -
   1.446 -        returns vbd device (or None)
   1.447 +        @param dom: domain
   1.448 +        @param vbd: vbd index
   1.449 +        @return: vbd device (or None)
   1.450          """
   1.451          return self.domain_devtype_get(dom, 'vbd', vbd)
   1.452  
   1.453      def domain_shadow_control(self, dom, op):
   1.454          """Shadow page control.
   1.455  
   1.456 -        dom domain
   1.457 -        op  operation
   1.458 +        @param dom: domain
   1.459 +        @param op:  operation
   1.460          """
   1.461          dom = int(dom)
   1.462          return xc.shadow_control(dom, op)
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Fri Jul 09 12:53:50 2004 +0000
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Jul 09 14:51:23 2004 +0000
     2.3 @@ -29,9 +29,35 @@ xendConsole = XendConsole.instance()
     2.4  import server.SrvDaemon
     2.5  xend = server.SrvDaemon.instance()
     2.6  
     2.7 +"""Flag for a block device backend domain."""
     2.8  SIF_BLK_BE_DOMAIN = (1<<4)
     2.9 +
    2.10 +"""Flag for a net device backend domain."""
    2.11  SIF_NET_BE_DOMAIN = (1<<5)
    2.12  
    2.13 +"""Shutdown code for poweroff."""
    2.14 +DOMAIN_POWEROFF = 0
    2.15 +"""Shutdown code for reboot."""
    2.16 +DOMAIN_REBOOT   = 1
    2.17 +"""Shutdown code for suspend."""
    2.18 +DOMAIN_SUSPEND  = 2
    2.19 +
    2.20 +"""Map shutdown codes to strings."""
    2.21 +shutdown_reasons = {
    2.22 +    DOMAIN_POWEROFF: "poweroff",
    2.23 +    DOMAIN_REBOOT  : "reboot",
    2.24 +    DOMAIN_SUSPEND : "suspend" }
    2.25 +
    2.26 +def shutdown_reason(code):
    2.27 +    """Get a shutdown reason from a code.
    2.28 +
    2.29 +    @param code: shutdown code
    2.30 +    @type  code: int
    2.31 +    @return: shutdown reason
    2.32 +    @rtype:  string
    2.33 +    """
    2.34 +    return shutdown_reasons.get(code, "?")
    2.35 +
    2.36  class VmError(ValueError):
    2.37      """Vm construction error."""
    2.38