diff options
author | emellor@ewan <emellor@ewan> | 2005-09-30 17:10:20 +0100 |
---|---|---|
committer | emellor@ewan <emellor@ewan> | 2005-09-30 17:10:20 +0100 |
commit | 42fb9678c9ee33b806ba4be14bf58a41146a09b0 (patch) | |
tree | 124d0170f22feb6530a411e756e918f2e90ce690 /tools | |
parent | db730ecdd132306732846b1ec26d8c5a7a873563 (diff) | |
download | xen-42fb9678c9ee33b806ba4be14bf58a41146a09b0.tar.gz xen-42fb9678c9ee33b806ba4be14bf58a41146a09b0.tar.bz2 xen-42fb9678c9ee33b806ba4be14bf58a41146a09b0.zip |
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>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/examples/xmexample.vmx | 13 | ||||
-rw-r--r-- | tools/examples/xmexample1 | 13 | ||||
-rw-r--r-- | tools/examples/xmexample2 | 13 | ||||
-rw-r--r-- | tools/examples/xmexample3 | 13 | ||||
-rw-r--r-- | tools/python/xen/xend/XendDomainInfo.py | 122 | ||||
-rw-r--r-- | tools/python/xen/xm/create.py | 44 |
6 files changed, 164 insertions, 54 deletions
diff --git a/tools/examples/xmexample.vmx b/tools/examples/xmexample.vmx index 9b1ca8f221..89f934ddd9 100644 --- a/tools/examples/xmexample.vmx +++ b/tools/examples/xmexample.vmx @@ -50,10 +50,15 @@ disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ] #---------------------------------------------------------------------------- # Configure the behaviour when a domain exits. There are three 'reasons' # for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify "destroy", meaning that the domain is cleaned up as normal, -# "restart", meaning that a new domain is started in place of the old one, or -# "preserve", meaning that no clean-up is done until the domain is manually -# destroyed (using xm destroy, for example). +# may specify: +# +# "destroy", meaning that the domain is cleaned up as normal; +# "restart", meaning that a new domain is started in place of the old +# one; +# "preserve", meaning that no clean-up is done until the domain is +# manually destroyed (using xm destroy, for example); or +# "rename-restart", meaning that the old domain is not cleaned up, but is +# renamed and a new domain started in its place. # # The default is # diff --git a/tools/examples/xmexample1 b/tools/examples/xmexample1 index bd2e70d9a2..be3af30a95 100644 --- a/tools/examples/xmexample1 +++ b/tools/examples/xmexample1 @@ -93,10 +93,15 @@ extra = "4" #---------------------------------------------------------------------------- # Configure the behaviour when a domain exits. There are three 'reasons' # for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify "destroy", meaning that the domain is cleaned up as normal, -# "restart", meaning that a new domain is started in place of the old one, or -# "preserve", meaning that no clean-up is done until the domain is manually -# destroyed (using xm destroy, for example). +# may specify: +# +# "destroy", meaning that the domain is cleaned up as normal; +# "restart", meaning that a new domain is started in place of the old +# one; +# "preserve", meaning that no clean-up is done until the domain is +# manually destroyed (using xm destroy, for example); or +# "rename-restart", meaning that the old domain is not cleaned up, but is +# renamed and a new domain started in its place. # # The default is # diff --git a/tools/examples/xmexample2 b/tools/examples/xmexample2 index fb7bd05fc5..8272e84ab5 100644 --- a/tools/examples/xmexample2 +++ b/tools/examples/xmexample2 @@ -129,10 +129,15 @@ extra = "4 VMID=%d usr=/dev/sda6" % vmid #---------------------------------------------------------------------------- # Configure the behaviour when a domain exits. There are three 'reasons' # for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify "destroy", meaning that the domain is cleaned up as normal, -# "restart", meaning that a new domain is started in place of the old one, or -# "preserve", meaning that no clean-up is done until the domain is manually -# destroyed (using xm destroy, for example). +# may specify: +# +# "destroy", meaning that the domain is cleaned up as normal; +# "restart", meaning that a new domain is started in place of the old +# one; +# "preserve", meaning that no clean-up is done until the domain is +# manually destroyed (using xm destroy, for example); or +# "rename-restart", meaning that the old domain is not cleaned up, but is +# renamed and a new domain started in its place. # # The default is # diff --git a/tools/examples/xmexample3 b/tools/examples/xmexample3 index e0e1775589..45211c7129 100644 --- a/tools/examples/xmexample3 +++ b/tools/examples/xmexample3 @@ -126,10 +126,15 @@ extra = "4 VMID=%d" % vmid #---------------------------------------------------------------------------- # Configure the behaviour when a domain exits. There are three 'reasons' # for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify "destroy", meaning that the domain is cleaned up as normal, -# "restart", meaning that a new domain is started in place of the old one, or -# "preserve", meaning that no clean-up is done until the domain is manually -# destroyed (using xm destroy, for example). +# may specify: +# +# "destroy", meaning that the domain is cleaned up as normal; +# "restart", meaning that a new domain is started in place of the old +# one; +# "preserve", meaning that no clean-up is done until the domain is +# manually destroyed (using xm destroy, for example); or +# "rename-restart", meaning that the old domain is not cleaned up, but is +# renamed and a new domain started in its place. # # The default is # diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index dac0affce6..5a4d145a6f 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -70,7 +70,8 @@ shutdown_reasons = { restart_modes = [ "restart", "destroy", - "preserve" + "preserve", + "rename-restart" ] STATE_VM_OK = "ok" @@ -653,21 +654,26 @@ class XendDomainInfo: restart_reason = 'crash' elif xeninfo['shutdown']: - reason = shutdown_reason(xeninfo['shutdown_reason']) + if self.readDom('xend/shutdown'): + # We've seen this shutdown already, but we are preserving + # the domain for debugging. Leave it alone. + pass + else: + reason = shutdown_reason(xeninfo['shutdown_reason']) - log.info('Domain has shutdown: name=%s id=%d reason=%s.', - self.info['name'], self.domid, reason) + log.info('Domain has shutdown: name=%s id=%d reason=%s.', + self.info['name'], self.domid, reason) - self.clearRestart() + self.clearRestart() - if reason == 'suspend': - self.state_set(STATE_VM_SUSPENDED) - # Don't destroy the domain. XendCheckpoint will do this - # once it has finished. - elif reason in ['poweroff', 'reboot']: - restart_reason = reason - else: - self.destroy() + if reason == 'suspend': + self.state_set(STATE_VM_SUSPENDED) + # Don't destroy the domain. XendCheckpoint will do + # this once it has finished. + elif reason in ['poweroff', 'reboot']: + restart_reason = reason + else: + self.destroy() else: # Domain is alive. If we are shutting it down, then check @@ -702,6 +708,8 @@ class XendDomainInfo: self.storeDom('xend/shutdown_start_time', time.time()) + ## private: + def clearRestart(self): self.removeDom("xend/shutdown_start_time") @@ -709,9 +717,10 @@ class XendDomainInfo: def maybeRestart(self, reason): # Dispatch to the correct method based upon the configured on_{reason} # behaviour. - {"destroy" : self.destroy, - "restart" : self.restart, - "preserve" : self.preserve}[self.info['on_' + reason]]() + {"destroy" : self.destroy, + "restart" : self.restart, + "preserve" : self.preserve, + "rename-restart" : self.renameRestart}[self.info['on_' + reason]]() def preserve(self): @@ -719,6 +728,10 @@ class XendDomainInfo: self.domid) + def renameRestart(self): + self.restart(True) + + def dumpCore(self): """Create a core dump for this domain. Nothrow guarantee.""" @@ -758,6 +771,8 @@ class XendDomainInfo: self.console_channel = None + ## public: + def setConsoleRef(self, ref): self.console_mfn = ref self.storeDom("console/ring-ref", ref) @@ -973,6 +988,10 @@ class XendDomainInfo: try: self.dompath = DOMROOT + str(self.domid) + # Ensure that the domain entry is clean. This prevents a stale + # shutdown_start_time from killing the domain, for example. + self.removeDom() + self.initDomain() self.construct_image() self.configure() @@ -1083,6 +1102,8 @@ class XendDomainInfo: log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.") + ## private: + def is_terminated(self): """Check if a domain has been terminated. """ @@ -1142,7 +1163,7 @@ class XendDomainInfo: log.error("Recovering from above exception.") self.storeDom(path, ret.port1) return ret - + def create_channel(self): """Create the channels to the domain. """ @@ -1163,6 +1184,9 @@ class XendDomainInfo: if self.image: self.image.createDeviceModel() + + ## public: + def device_create(self, dev_config): """Create a new device. @@ -1183,21 +1207,7 @@ class XendDomainInfo: self.configureDevice(deviceClass, devid, dev_config) - def restart_needed(self, reason): - """Determine if the vm needs to be restarted when shutdown - for the given reason. - - @param reason: shutdown reason - @return True if needs restart, False otherwise - """ - if self.info['restart_mode'] == RESTART_NEVER: - return False - if self.info['restart_mode'] == RESTART_ALWAYS: - return True - if self.info['restart_mode'] == RESTART_ONREBOOT: - return reason == 'reboot' - return False - + ## private: def restart_check(self): """Check if domain restart is OK. @@ -1216,15 +1226,17 @@ class XendDomainInfo: self.restart_count += 1 - def restart(self): - """Restart the domain after it has exited. """ + def restart(self, rename = False): + """Restart the domain after it has exited. + + @param rename True if the old domain is to be renamed and preserved, + False if it is to be destroyed. + """ # self.restart_check() config = self.sxpr() - self.cleanupDomain() - if self.readVm('xend/restart_in_progress'): log.error('Xend failed during restart of domain %d. ' 'Refusing to restart to avoid loops.', @@ -1235,7 +1247,12 @@ class XendDomainInfo: self.writeVm('xend/restart_in_progress', 'True') try: - self.destroy() + if rename: + self.preserveShutdownDomain() + else: + self.cleanupDomain() + self.destroy() + try: xd = get_component('xen.xend.XendDomain') xd.domain_unpause(xd.domain_create(config).getDomid()) @@ -1248,6 +1265,37 @@ class XendDomainInfo: # self.exportToDB() + def preserveShutdownDomain(self): + """Preserve a domain that has been shut down, by giving it a new UUID, + cloning the VM details, and giving it a new name. This allows us to + keep this domain for debugging, but restart a new one in its place + preserving the restart semantics (name and UUID preserved). + """ + + new_name = self.generateShutdownName() + new_uuid = getUuid() + log.info("Renaming dead domain %s (%d, %s) to %s (%s).", + self.info['name'], self.domid, self.uuid, new_name, new_uuid) + self.release_devices() + self.info['name'] = new_name + self.uuid = new_uuid + self.vmpath = VMROOT + new_uuid + self.storeVmDetails() + self.storeDom('vm', self.vmpath) + self.storeDom('xend/shutdown', 'True') + + + def generateShutdownName(self): + n = 1 + while True: + name = "%s-%d" % (self.info['name'], n) + try: + self.check_name(name) + return name + except VmError: + n += 1 + + def configure_bootloader(self): if not self.info['bootloader']: return diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index a599890053..a6498c72ad 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -163,11 +163,47 @@ gopts.var('cpu_weight', val='WEIGHT', gopts.var('restart', val='onreboot|always|never', fn=set_value, default=None, - use="""Whether the domain should be restarted on exit. + use="""Deprecated. Use on_poweroff, on_reboot, and on_crash + instead. + + Whether the domain should be restarted on exit. - onreboot: restart on exit with shutdown code reboot - always: always restart on exit, ignore exit code - never: never restart on exit, ignore exit code""") +gopts.var('on_poweroff', val='destroy|restart|preserve|rename-restart', + fn=set_value, default=None, + use="""Behaviour when a domain exits with reason 'poweroff'. + - destroy: the domain is cleaned up as normal; + - restart: a new domain is started in place of the old one; + - preserve: no clean-up is done until the domain is manually + destroyed (using xm destroy, for example); + - rename-restart: the old domain is not cleaned up, but is + renamed and a new domain started in its place. + """) + +gopts.var('on_reboot', val='destroy|restart|preserve|rename-restart', + fn=set_value, default=None, + use="""Behaviour when a domain exits with reason 'reboot'. + - destroy: the domain is cleaned up as normal; + - restart: a new domain is started in place of the old one; + - preserve: no clean-up is done until the domain is manually + destroyed (using xm destroy, for example); + - rename-restart: the old domain is not cleaned up, but is + renamed and a new domain started in its place. + """) + +gopts.var('on_crash', val='destroy|restart|preserve|rename-restart', + fn=set_value, default=None, + use="""Behaviour when a domain exits with reason 'crash'. + - destroy: the domain is cleaned up as normal; + - restart: a new domain is started in place of the old one; + - preserve: no clean-up is done until the domain is manually + destroyed (using xm destroy, for example); + - rename-restart: the old domain is not cleaned up, but is + renamed and a new domain started in its place. + """) + gopts.var('blkif', val='no|yes', fn=set_bool, default=0, use="Make the domain a block device backend.") @@ -536,6 +572,12 @@ def make_config(opts, vals): config.append(['backend', ['tpmif']]) if vals.restart: config.append(['restart', vals.restart]) + if vals.on_poweroff: + config.append(['on_poweroff', vals.on_poweroff]) + if vals.on_reboot: + config.append(['on_reboot', vals.on_reboot]) + if vals.on_crash: + config.append(['on_crash', vals.on_crash]) if vals.bootloader: config.append(['bootloader', vals.bootloader]) |