aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authoremellor@ewan <emellor@ewan>2005-09-30 17:10:20 +0100
committeremellor@ewan <emellor@ewan>2005-09-30 17:10:20 +0100
commit42fb9678c9ee33b806ba4be14bf58a41146a09b0 (patch)
tree124d0170f22feb6530a411e756e918f2e90ce690 /tools
parentdb730ecdd132306732846b1ec26d8c5a7a873563 (diff)
downloadxen-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.vmx13
-rw-r--r--tools/examples/xmexample113
-rw-r--r--tools/examples/xmexample213
-rw-r--r--tools/examples/xmexample313
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py122
-rw-r--r--tools/python/xen/xm/create.py44
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])