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>
This commit is contained in:
emellor@ewan committed 2005-09-30 17:10:20 +01:00
1 parent db730ecdd1
commit 42fb9678c9
6 files changed
+166 -56

No files matched your search

+87 -39
View File
@@ -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'])
log.info('Domain has shutdown: name=%s id=%d reason=%s.',
self.info['name'], self.domid, reason)
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
if self.readDom('xend/shutdown'):
# We've seen this shutdown already, but we are preserving
# the domain for debugging. Leave it alone.
pass
else:
self.destroy()
reason = shutdown_reason(xeninfo['shutdown_reason'])
log.info('Domain has shutdown: name=%s id=%d reason=%s.',
self.info['name'], self.domid, reason)
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()
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
+43 -1
View File
@@ -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])
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.