ia64/xen-unstable

changeset 7156:244f1aa98d30

Add the config file parsing for the on_{poweroff,reboot,crash} options, so that
they actually take effect. Added behaviour "rename-restart" for debugging
purposes, that renames the domain out of the way, preserving it for debugging,
but starts a new domain too.

Add explicit remove of old domain paths when creating a new domain, to avoid
stale information affecting us (by shutting the domain down, for example).

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Fri Sep 30 17:10:20 2005 +0100 (2005-09-30)
parents 468ad17f9970
children 9918d8c3e116
files tools/examples/xmexample.vmx tools/examples/xmexample1 tools/examples/xmexample2 tools/examples/xmexample3 tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xm/create.py
line diff
     1.1 --- a/tools/examples/xmexample.vmx	Fri Sep 30 17:05:08 2005 +0100
     1.2 +++ b/tools/examples/xmexample.vmx	Fri Sep 30 17:10:20 2005 +0100
     1.3 @@ -50,10 +50,15 @@ disk = [ 'file:/var/images/min-el3-i386.
     1.4  #----------------------------------------------------------------------------
     1.5  # Configure the behaviour when a domain exits.  There are three 'reasons'
     1.6  # for a domain to stop: poweroff, reboot, and crash.  For each of these you
     1.7 -# may specify "destroy", meaning that the domain is cleaned up as normal,
     1.8 -# "restart", meaning that a new domain is started in place of the old one, or
     1.9 -# "preserve", meaning that no clean-up is done until the domain is manually
    1.10 -# destroyed (using xm destroy, for example).
    1.11 +# may specify:
    1.12 +#
    1.13 +#   "destroy",        meaning that the domain is cleaned up as normal;
    1.14 +#   "restart",        meaning that a new domain is started in place of the old
    1.15 +#                     one;
    1.16 +#   "preserve",       meaning that no clean-up is done until the domain is
    1.17 +#                     manually destroyed (using xm destroy, for example); or
    1.18 +#   "rename-restart", meaning that the old domain is not cleaned up, but is
    1.19 +#                     renamed and a new domain started in its place.
    1.20  #
    1.21  # The default is
    1.22  #
     2.1 --- a/tools/examples/xmexample1	Fri Sep 30 17:05:08 2005 +0100
     2.2 +++ b/tools/examples/xmexample1	Fri Sep 30 17:10:20 2005 +0100
     2.3 @@ -93,10 +93,15 @@ extra = "4"
     2.4  #----------------------------------------------------------------------------
     2.5  # Configure the behaviour when a domain exits.  There are three 'reasons'
     2.6  # for a domain to stop: poweroff, reboot, and crash.  For each of these you
     2.7 -# may specify "destroy", meaning that the domain is cleaned up as normal,
     2.8 -# "restart", meaning that a new domain is started in place of the old one, or
     2.9 -# "preserve", meaning that no clean-up is done until the domain is manually
    2.10 -# destroyed (using xm destroy, for example).
    2.11 +# may specify:
    2.12 +#
    2.13 +#   "destroy",        meaning that the domain is cleaned up as normal;
    2.14 +#   "restart",        meaning that a new domain is started in place of the old
    2.15 +#                     one;
    2.16 +#   "preserve",       meaning that no clean-up is done until the domain is
    2.17 +#                     manually destroyed (using xm destroy, for example); or
    2.18 +#   "rename-restart", meaning that the old domain is not cleaned up, but is
    2.19 +#                     renamed and a new domain started in its place.
    2.20  #
    2.21  # The default is
    2.22  #
     3.1 --- a/tools/examples/xmexample2	Fri Sep 30 17:05:08 2005 +0100
     3.2 +++ b/tools/examples/xmexample2	Fri Sep 30 17:10:20 2005 +0100
     3.3 @@ -129,10 +129,15 @@ extra = "4 VMID=%d usr=/dev/sda6" % vmid
     3.4  #----------------------------------------------------------------------------
     3.5  # Configure the behaviour when a domain exits.  There are three 'reasons'
     3.6  # for a domain to stop: poweroff, reboot, and crash.  For each of these you
     3.7 -# may specify "destroy", meaning that the domain is cleaned up as normal,
     3.8 -# "restart", meaning that a new domain is started in place of the old one, or
     3.9 -# "preserve", meaning that no clean-up is done until the domain is manually
    3.10 -# destroyed (using xm destroy, for example).
    3.11 +# may specify:
    3.12 +#
    3.13 +#   "destroy",        meaning that the domain is cleaned up as normal;
    3.14 +#   "restart",        meaning that a new domain is started in place of the old
    3.15 +#                     one;
    3.16 +#   "preserve",       meaning that no clean-up is done until the domain is
    3.17 +#                     manually destroyed (using xm destroy, for example); or
    3.18 +#   "rename-restart", meaning that the old domain is not cleaned up, but is
    3.19 +#                     renamed and a new domain started in its place.
    3.20  #
    3.21  # The default is
    3.22  #
     4.1 --- a/tools/examples/xmexample3	Fri Sep 30 17:05:08 2005 +0100
     4.2 +++ b/tools/examples/xmexample3	Fri Sep 30 17:10:20 2005 +0100
     4.3 @@ -126,10 +126,15 @@ extra = "4 VMID=%d" % vmid
     4.4  #----------------------------------------------------------------------------
     4.5  # Configure the behaviour when a domain exits.  There are three 'reasons'
     4.6  # for a domain to stop: poweroff, reboot, and crash.  For each of these you
     4.7 -# may specify "destroy", meaning that the domain is cleaned up as normal,
     4.8 -# "restart", meaning that a new domain is started in place of the old one, or
     4.9 -# "preserve", meaning that no clean-up is done until the domain is manually
    4.10 -# destroyed (using xm destroy, for example).
    4.11 +# may specify:
    4.12 +#
    4.13 +#   "destroy",        meaning that the domain is cleaned up as normal;
    4.14 +#   "restart",        meaning that a new domain is started in place of the old
    4.15 +#                     one;
    4.16 +#   "preserve",       meaning that no clean-up is done until the domain is
    4.17 +#                     manually destroyed (using xm destroy, for example); or
    4.18 +#   "rename-restart", meaning that the old domain is not cleaned up, but is
    4.19 +#                     renamed and a new domain started in its place.
    4.20  #
    4.21  # The default is
    4.22  #
     5.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Fri Sep 30 17:05:08 2005 +0100
     5.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Sep 30 17:10:20 2005 +0100
     5.3 @@ -70,7 +70,8 @@ shutdown_reasons = {
     5.4  restart_modes = [
     5.5      "restart",
     5.6      "destroy",
     5.7 -    "preserve"
     5.8 +    "preserve",
     5.9 +    "rename-restart"
    5.10      ]
    5.11  
    5.12  STATE_VM_OK         = "ok"
    5.13 @@ -653,21 +654,26 @@ class XendDomainInfo:
    5.14                  restart_reason = 'crash'
    5.15  
    5.16              elif xeninfo['shutdown']:
    5.17 -                reason = shutdown_reason(xeninfo['shutdown_reason'])
    5.18 +                if self.readDom('xend/shutdown'):
    5.19 +                    # We've seen this shutdown already, but we are preserving
    5.20 +                    # the domain for debugging.  Leave it alone.
    5.21 +                    pass
    5.22 +                else:
    5.23 +                    reason = shutdown_reason(xeninfo['shutdown_reason'])
    5.24  
    5.25 -                log.info('Domain has shutdown: name=%s id=%d reason=%s.',
    5.26 -                         self.info['name'], self.domid, reason)
    5.27 -
    5.28 -                self.clearRestart()
    5.29 +                    log.info('Domain has shutdown: name=%s id=%d reason=%s.',
    5.30 +                             self.info['name'], self.domid, reason)
    5.31  
    5.32 -                if reason == 'suspend':
    5.33 -                    self.state_set(STATE_VM_SUSPENDED)
    5.34 -                    # Don't destroy the domain.  XendCheckpoint will do this
    5.35 -                    # once it has finished.
    5.36 -                elif reason in ['poweroff', 'reboot']:
    5.37 -                    restart_reason = reason
    5.38 -                else:
    5.39 -                    self.destroy()
    5.40 +                    self.clearRestart()
    5.41 +
    5.42 +                    if reason == 'suspend':
    5.43 +                        self.state_set(STATE_VM_SUSPENDED)
    5.44 +                        # Don't destroy the domain.  XendCheckpoint will do
    5.45 +                        # this once it has finished.
    5.46 +                    elif reason in ['poweroff', 'reboot']:
    5.47 +                        restart_reason = reason
    5.48 +                    else:
    5.49 +                        self.destroy()
    5.50  
    5.51              else:
    5.52                  # Domain is alive.  If we are shutting it down, then check
    5.53 @@ -702,6 +708,8 @@ class XendDomainInfo:
    5.54              self.storeDom('xend/shutdown_start_time', time.time())
    5.55  
    5.56  
    5.57 +    ## private:
    5.58 +
    5.59      def clearRestart(self):
    5.60          self.removeDom("xend/shutdown_start_time")
    5.61  
    5.62 @@ -709,9 +717,10 @@ class XendDomainInfo:
    5.63      def maybeRestart(self, reason):
    5.64          # Dispatch to the correct method based upon the configured on_{reason}
    5.65          # behaviour.
    5.66 -        {"destroy"  : self.destroy,
    5.67 -         "restart"  : self.restart,
    5.68 -         "preserve" : self.preserve}[self.info['on_' + reason]]()
    5.69 +        {"destroy"        : self.destroy,
    5.70 +         "restart"        : self.restart,
    5.71 +         "preserve"       : self.preserve,
    5.72 +         "rename-restart" : self.renameRestart}[self.info['on_' + reason]]()
    5.73  
    5.74  
    5.75      def preserve(self):
    5.76 @@ -719,6 +728,10 @@ class XendDomainInfo:
    5.77                   self.domid)
    5.78  
    5.79  
    5.80 +    def renameRestart(self):
    5.81 +        self.restart(True)
    5.82 +
    5.83 +
    5.84      def dumpCore(self):
    5.85          """Create a core dump for this domain.  Nothrow guarantee."""
    5.86          
    5.87 @@ -758,6 +771,8 @@ class XendDomainInfo:
    5.88          self.console_channel = None
    5.89  
    5.90  
    5.91 +    ## public:
    5.92 +
    5.93      def setConsoleRef(self, ref):
    5.94          self.console_mfn = ref
    5.95          self.storeDom("console/ring-ref", ref)
    5.96 @@ -973,6 +988,10 @@ class XendDomainInfo:
    5.97          try:
    5.98              self.dompath = DOMROOT + str(self.domid)
    5.99  
   5.100 +            # Ensure that the domain entry is clean.  This prevents a stale
   5.101 +            # shutdown_start_time from killing the domain, for example.
   5.102 +            self.removeDom()
   5.103 +
   5.104              self.initDomain()
   5.105              self.construct_image()
   5.106              self.configure()
   5.107 @@ -1083,6 +1102,8 @@ class XendDomainInfo:
   5.108              log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
   5.109  
   5.110  
   5.111 +    ## private:
   5.112 +
   5.113      def is_terminated(self):
   5.114          """Check if a domain has been terminated.
   5.115          """
   5.116 @@ -1142,7 +1163,7 @@ class XendDomainInfo:
   5.117                      log.error("Recovering from above exception.")
   5.118          self.storeDom(path, ret.port1)
   5.119          return ret
   5.120 -        
   5.121 +
   5.122      def create_channel(self):
   5.123          """Create the channels to the domain.
   5.124          """
   5.125 @@ -1163,6 +1184,9 @@ class XendDomainInfo:
   5.126          if self.image:
   5.127              self.image.createDeviceModel()
   5.128  
   5.129 +
   5.130 +    ## public:
   5.131 +
   5.132      def device_create(self, dev_config):
   5.133          """Create a new device.
   5.134  
   5.135 @@ -1183,21 +1207,7 @@ class XendDomainInfo:
   5.136          self.configureDevice(deviceClass, devid, dev_config)
   5.137  
   5.138  
   5.139 -    def restart_needed(self, reason):
   5.140 -        """Determine if the vm needs to be restarted when shutdown
   5.141 -        for the given reason.
   5.142 -
   5.143 -        @param reason: shutdown reason
   5.144 -        @return True if needs restart, False otherwise
   5.145 -        """
   5.146 -        if self.info['restart_mode'] == RESTART_NEVER:
   5.147 -            return False
   5.148 -        if self.info['restart_mode'] == RESTART_ALWAYS:
   5.149 -            return True
   5.150 -        if self.info['restart_mode'] == RESTART_ONREBOOT:
   5.151 -            return reason == 'reboot'
   5.152 -        return False
   5.153 -
   5.154 +    ## private:
   5.155  
   5.156      def restart_check(self):
   5.157          """Check if domain restart is OK.
   5.158 @@ -1216,15 +1226,17 @@ class XendDomainInfo:
   5.159          self.restart_count += 1
   5.160  
   5.161  
   5.162 -    def restart(self):
   5.163 -        """Restart the domain after it has exited. """
   5.164 +    def restart(self, rename = False):
   5.165 +        """Restart the domain after it has exited.
   5.166 +
   5.167 +        @param rename True if the old domain is to be renamed and preserved,
   5.168 +        False if it is to be destroyed.
   5.169 +        """
   5.170  
   5.171          #            self.restart_check()
   5.172  
   5.173          config = self.sxpr()
   5.174  
   5.175 -        self.cleanupDomain()
   5.176 -
   5.177          if self.readVm('xend/restart_in_progress'):
   5.178              log.error('Xend failed during restart of domain %d.  '
   5.179                        'Refusing to restart to avoid loops.',
   5.180 @@ -1235,7 +1247,12 @@ class XendDomainInfo:
   5.181          self.writeVm('xend/restart_in_progress', 'True')
   5.182  
   5.183          try:
   5.184 -            self.destroy()
   5.185 +            if rename:
   5.186 +                self.preserveShutdownDomain()
   5.187 +            else:
   5.188 +                self.cleanupDomain()
   5.189 +                self.destroy()
   5.190 +                
   5.191              try:
   5.192                  xd = get_component('xen.xend.XendDomain')
   5.193                  xd.domain_unpause(xd.domain_create(config).getDomid())
   5.194 @@ -1248,6 +1265,37 @@ class XendDomainInfo:
   5.195          #        self.exportToDB()
   5.196  
   5.197  
   5.198 +    def preserveShutdownDomain(self):
   5.199 +        """Preserve a domain that has been shut down, by giving it a new UUID,
   5.200 +        cloning the VM details, and giving it a new name.  This allows us to
   5.201 +        keep this domain for debugging, but restart a new one in its place
   5.202 +        preserving the restart semantics (name and UUID preserved).
   5.203 +        """
   5.204 +        
   5.205 +        new_name = self.generateShutdownName()
   5.206 +        new_uuid = getUuid()
   5.207 +        log.info("Renaming dead domain %s (%d, %s) to %s (%s).",
   5.208 +                 self.info['name'], self.domid, self.uuid, new_name, new_uuid)
   5.209 +        self.release_devices()
   5.210 +        self.info['name'] = new_name
   5.211 +        self.uuid = new_uuid
   5.212 +        self.vmpath = VMROOT + new_uuid
   5.213 +        self.storeVmDetails()
   5.214 +        self.storeDom('vm', self.vmpath)
   5.215 +        self.storeDom('xend/shutdown', 'True')
   5.216 +
   5.217 +
   5.218 +    def generateShutdownName(self):
   5.219 +        n = 1
   5.220 +        while True:
   5.221 +            name = "%s-%d" % (self.info['name'], n)
   5.222 +            try:
   5.223 +                self.check_name(name)
   5.224 +                return name
   5.225 +            except VmError:
   5.226 +                n += 1
   5.227 +
   5.228 +
   5.229      def configure_bootloader(self):
   5.230          if not self.info['bootloader']:
   5.231              return
     6.1 --- a/tools/python/xen/xm/create.py	Fri Sep 30 17:05:08 2005 +0100
     6.2 +++ b/tools/python/xen/xm/create.py	Fri Sep 30 17:10:20 2005 +0100
     6.3 @@ -163,11 +163,47 @@ gopts.var('cpu_weight', val='WEIGHT',
     6.4  
     6.5  gopts.var('restart', val='onreboot|always|never',
     6.6            fn=set_value, default=None,
     6.7 -          use="""Whether the domain should be restarted on exit.
     6.8 +          use="""Deprecated.  Use on_poweroff, on_reboot, and on_crash
     6.9 +          instead.
    6.10 +
    6.11 +          Whether the domain should be restarted on exit.
    6.12            - onreboot: restart on exit with shutdown code reboot
    6.13            - always:   always restart on exit, ignore exit code
    6.14            - never:    never restart on exit, ignore exit code""")
    6.15  
    6.16 +gopts.var('on_poweroff', val='destroy|restart|preserve|rename-restart',
    6.17 +          fn=set_value, default=None,
    6.18 +          use="""Behaviour when a domain exits with reason 'poweroff'.
    6.19 +          - destroy:        the domain is cleaned up as normal;
    6.20 +          - restart:        a new domain is started in place of the old one;
    6.21 +          - preserve:       no clean-up is done until the domain is manually
    6.22 +                            destroyed (using xm destroy, for example);
    6.23 +          - rename-restart: the old domain is not cleaned up, but is
    6.24 +                            renamed and a new domain started in its place.
    6.25 +          """)
    6.26 +
    6.27 +gopts.var('on_reboot', val='destroy|restart|preserve|rename-restart',
    6.28 +          fn=set_value, default=None,
    6.29 +          use="""Behaviour when a domain exits with reason 'reboot'.
    6.30 +          - destroy:        the domain is cleaned up as normal;
    6.31 +          - restart:        a new domain is started in place of the old one;
    6.32 +          - preserve:       no clean-up is done until the domain is manually
    6.33 +                            destroyed (using xm destroy, for example);
    6.34 +          - rename-restart: the old domain is not cleaned up, but is
    6.35 +                            renamed and a new domain started in its place.
    6.36 +          """)
    6.37 +
    6.38 +gopts.var('on_crash', val='destroy|restart|preserve|rename-restart',
    6.39 +          fn=set_value, default=None,
    6.40 +          use="""Behaviour  when a domain exits with reason 'crash'.
    6.41 +          - destroy:        the domain is cleaned up as normal;
    6.42 +          - restart:        a new domain is started in place of the old one;
    6.43 +          - preserve:       no clean-up is done until the domain is manually
    6.44 +                            destroyed (using xm destroy, for example);
    6.45 +          - rename-restart: the old domain is not cleaned up, but is
    6.46 +                            renamed and a new domain started in its place.
    6.47 +          """)
    6.48 +
    6.49  gopts.var('blkif', val='no|yes',
    6.50            fn=set_bool, default=0,
    6.51            use="Make the domain a block device backend.")
    6.52 @@ -536,6 +572,12 @@ def make_config(opts, vals):
    6.53          config.append(['backend', ['tpmif']])
    6.54      if vals.restart:
    6.55          config.append(['restart', vals.restart])
    6.56 +    if vals.on_poweroff:
    6.57 +        config.append(['on_poweroff', vals.on_poweroff])
    6.58 +    if vals.on_reboot:
    6.59 +        config.append(['on_reboot', vals.on_reboot])
    6.60 +    if vals.on_crash:
    6.61 +        config.append(['on_crash', vals.on_crash])
    6.62  
    6.63      if vals.bootloader:
    6.64          config.append(['bootloader', vals.bootloader])