bitkeeper revision 1.1041.5.5 (40e97f82YUOF-rGuIapKOE73WUHZcg)

Add control over domain restart on shutdown.
This commit is contained in:
mjw@wray-m-3.hpl.hp.com committed 2004-07-05 16:19:14 +00:00
1 parent 6a30406587
commit 1c894096e7
8 files changed
+193 -36

No files matched your search

+3 -2
View File
@@ -225,9 +225,10 @@ class Xend:
return xend_call(self.domainurl(id),
{'op' : 'pause'})
def xend_domain_shutdown(self, id):
def xend_domain_shutdown(self, id, reason):
return xend_call(self.domainurl(id),
{'op' : 'shutdown'})
{'op' : 'shutdown',
'reason' : reason })
def xend_domain_destroy(self, id):
return xend_call(self.domainurl(id),
+131 -10
View File
@@ -5,8 +5,10 @@
Needs to be persistent for one uptime.
"""
import sys
import traceback
from twisted.internet import defer
from twisted.internet import reactor
import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
@@ -28,10 +30,19 @@ __all__ = [ "XendDomain" ]
class XendDomain:
"""Index of all domains. Singleton.
"""
"""Path to domain database."""
dbpath = "domain"
"""Table of domain info indexed by domain id."""
domain = {}
"""Table of configs for domain restart, indexed by domain id."""
restarts = {}
"""Table of delayed calls."""
schedule = {}
def __init__(self):
self.xconsole = XendConsole.instance()
# Table of domain info indexed by domain id.
@@ -49,6 +60,53 @@ class XendDomain:
print 'XendDomain> virq', val
self.reap()
def schedule_later(self, _delay, _name, _fn, *args):
"""Schedule a function to be called later (if not already scheduled).
_delay delay in seconds
_name schedule name
_fn function
args arguments
"""
if self.schedule.get(_name): return
self.schedule[_name] = reactor.callLater(_delay, _fn, *args)
def schedule_cancel(self, name):
"""Cancel a scheduled function call.
name schedule name to cancel
"""
callid = self.schedule.get(name)
if not callid:
return
if callid.active():
callid.cancel()
del self.schedule[name]
def reap_schedule(self, delay=0):
"""Schedule reap to be called later.
delay delay in seconds
"""
self.schedule_later(delay, 'reap', self.reap)
def reap_cancel(self):
"""Cancel any scheduled reap.
"""
self.schedule_cancel('reap')
def refresh_schedule(self, delay=0):
"""Schedule refresh to be called later.
delay delay in seconds
"""
self.schedule_later(delay, 'refresh', self.refresh)
def refresh_cancel(self):
"""Cancel any scheduled refresh.
"""
self.schedule_cancel('refresh')
def rm_all(self):
"""Remove all domain info. Used after reboot.
"""
@@ -145,6 +203,7 @@ class XendDomain:
"""Look for domains that have crashed or stopped.
Tidy them up.
"""
self.reap_cancel()
print 'XendDomain>reap>'
domlist = xc.domain_getinfo()
casualties = []
@@ -158,12 +217,14 @@ class XendDomain:
for d in casualties:
id = str(d['dom'])
print 'XendDomain>reap> died id=', id, d
self.domain_destroy(id, refresh=0)
self.final_domain_destroy(id)
print 'XendDomain>reap<'
def refresh(self):
"""Refresh domain list from Xen.
"""
self.refresh_cancel()
print 'XendDomain>refresh>'
domlist = xc.domain_getinfo()
# Index the domlist by id.
# Add entries for any domains we don't know about.
@@ -184,7 +245,7 @@ class XendDomain:
d.update(dominfo)
else:
self._delete_domain(d.id)
self.reap()
self.reap_schedule(1)
def refresh_domain(self, id):
"""Refresh information for a single domain.
@@ -267,21 +328,70 @@ class XendDomain:
"""Shutdown domain (nicely).
id domain id
reason shutdown type: poweroff, reboot, halt
reason shutdown type: poweroff, reboot, suspend, halt
"""
dom = int(id)
if dom <= 0:
return 0
self.domain_restart_schedule(id, reason)
eserver.inject('xend.domain.shutdown', [id, reason])
if reason == 'halt':
reason = 'poweroff'
val = xend.domain_shutdown(dom, reason)
self.refresh()
self.refresh_schedule()
return val
def domain_destroy(self, id, refresh=1):
"""Terminate domain immediately.
def domain_restart_schedule(self, id, reason):
"""Schedule a restart for a domain if it needs one.
id domain id
reason shutdown reason
"""
if id in self.restarts:
# Don't schedule if already there.
return
restart = 0
if reason in ['poweroff', 'reboot']:
dominfo = self.domain.get(id)
if dominfo and (dominfo.autorestart or reason == 'reboot'):
restart = 1
# Clear autorestart flag to avoid multiple restarts.
dominfo.autorestart = 0
if restart:
self.restarts[id] = dominfo.config
def domain_restart_cancel(self, id):
"""Cancel any restart scheduled for a domain.
id domain id
"""
dominfo = self.domain.get(id)
if dominfo:
dominfo.autorestart = 0
if id in self.restarts:
del self.restarts[id]
def domain_restarts(self):
"""Execute any scheduled domain restarts for domains that have gone.
"""
for id in self.restarts.keys():
if id in self.domain:
# Don't execute restart for domains still running.
continue
config = self.restarts[id]
# Remove it from the restarts.
del self.restarts[id]
try:
self.domain_create(config)
except:
print >>sys.stderr, "XendDomain> Exception restarting domain"
traceback.print_exc(sys.stderr)
def final_domain_destroy(self, id):
"""Final destruction of a domain..
id domain id
refresh send a domain destroy event if true
"""
dom = int(id)
if dom <= 0:
@@ -292,15 +402,26 @@ class XendDomain:
val = dominfo.destroy()
else:
val = xc.domain_destroy(dom=dom)
if refresh: self.refresh()
return val
def domain_destroy(self, id):
"""Terminate domain immediately.
Camcels any restart for the domain.
id domain id
"""
self.domain_restart_cancel(id)
val = self.final_domain_destroy(id)
self.refresh_schedule()
return val
def domain_migrate(self, id, dst):
"""Start domain migration.
id domain id
"""
# Need a cancel too?
# Don't forget to cancel restart for it.
pass
def domain_save(self, id, dst, progress=0):
+4
View File
@@ -362,6 +362,8 @@ class XendDomainInfo:
self.state = self.STATE_OK
#todo: set to migrate info if migrating
self.migrate = None
#Whether to auto-restart
self.autorestart = 0
def setdom(self, dom):
self.dom = int(dom)
@@ -418,6 +420,8 @@ class XendDomainInfo:
try:
self.name = sxp.child_value(config, 'name')
self.memory = int(sxp.child_value(config, 'memory', '128'))
if sxp.child(config, 'autorestart', None):
self.autorestart = 1
self.configure_backends()
image = sxp.child_value(config, 'image')
image_name = sxp.name(image)
+5 -1
View File
@@ -27,7 +27,11 @@ class SrvDomain(SrvDir):
return val
def op_shutdown(self, op, req):
val = self.xd.domain_shutdown(self.dom.id)
#val = self.xd.domain_shutdown(self.dom.id)
fn = FormFn(self.xd.domain_shutdown,
[['dom', 'int'],
['reason', 'str']])
val = fn(req.args, {'dom': self.dom.id})
req.setResponseCode(202)
req.setHeader("Location", "%s/.." % req.prePathURL())
return val
+6
View File
@@ -101,6 +101,10 @@ gopts.opt('memory', short='m', val='MEMORY',
fn=set_value, default=128,
use="Domain memory in MB.")
gopts.opt('autorestart',
fn=set_true, default=0,
use="Whether to restart the domain on exit.")
gopts.opt('blkif',
fn=set_true, default=0,
use="Make the domain a block device backend.")
@@ -271,6 +275,8 @@ def make_config(opts):
config.append(['backend', ['blkif']])
if opts.netif:
config.append(['backend', ['netif']])
if opts.autorestart:
config.append(['autorestart'])
configure_image(config, opts)
config_devs = []
+29 -6
View File
@@ -1,4 +1,5 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
"""Domain shutdown.
"""
import string
@@ -10,7 +11,8 @@ from xen.xm.opts import *
gopts = Opts(use="""[options] [DOM]
Shutdown one or more domains gracefully.""")
Shutdown one or more domains gracefully.
""")
gopts.opt('help', short='h',
fn=set_true, default=0,
@@ -24,18 +26,22 @@ gopts.opt('wait', short='w',
fn=set_true, default=0,
use='Wait for shutdown to complete.')
gopts.opt('norestart', short='n',
gopts.opt('halt', short='H',
fn=set_true, default=0,
use='Prevent domain restart.')
use='Shutdown without reboot.')
def shutdown(opts, doms, wait):
gopts.opt('reboot', short='R',
fn=set_true, default=0,
use='Shutdown and reboot.')
def shutdown(opts, doms, mode, wait):
def domains():
return [ int(a) for a in server.xend_domains() ]
if doms == None: doms = domains()
if 0 in doms:
doms.remove(0)
for d in doms:
server.xend_domain_shutdown(d)
server.xend_domain_shutdown(d, mode)
if wait:
while doms:
alive = domains()
@@ -49,6 +55,21 @@ def shutdown(opts, doms, wait):
time.sleep(1)
opts.info("All domains terminated")
def shutdown_mode(opts):
mode = 'poweroff'
if opts.vals.wait:
mode = 'halt'
if opts.vals.reboot:
opts.err("Can't specify wait and reboot")
else:
if opts.vals.halt and opts.vals.reboot:
opts.err("Can't specify halt and reboot")
if opts.vals.halt:
mode = 'halt'
elif opts.vals.reboot:
mode = 'reboot'
return mode
def main_all(opts, args):
shutdown(opts, None, opts.vals.wait)
@@ -59,7 +80,9 @@ def main_dom(opts, args):
domid = int(dom)
except:
opts.err('Invalid domain: ' + dom)
shutdown(opts, [ domid ], opts.vals.wait)
mode = shutdown_mode(opts)
shutdown(opts, [ domid ], mode, opts.vals.wait)
def main(argv):
opts = gopts
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.