ia64/xen-unstable
changeset 1673:93d9954ab06c
bitkeeper revision 1.1041.5.5 (40e97f82YUOF-rGuIapKOE73WUHZcg)
Add control over domain restart on shutdown.
Add control over domain restart on shutdown.
author | mjw@wray-m-3.hpl.hp.com |
---|---|
date | Mon Jul 05 16:19:14 2004 +0000 (2004-07-05) |
parents | 025e093088ad |
children | d3666e462d59 |
files | tools/examples/xmdefaults tools/examples/xmnetbsd tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xm/create.py tools/python/xen/xm/shutdown.py |
line diff
1.1 --- a/tools/examples/xmdefaults Mon Jul 05 08:29:44 2004 +0000 1.2 +++ b/tools/examples/xmdefaults Mon Jul 05 16:19:14 2004 +0000 1.3 @@ -2,7 +2,6 @@ 1.4 #============================================================================ 1.5 # Python defaults setup for 'xm create'. 1.6 # Edit this file to reflect the configuration of your system. 1.7 - 1.8 #============================================================================ 1.9 1.10 # Define script variables here. 1.11 @@ -94,6 +93,6 @@ extra = "4 VMID=%d usr=/dev/sda6" % vmid 1.12 #---------------------------------------------------------------------------- 1.13 # Set according to whether you want the domain restarted when it exits. 1.14 # The default is False. 1.15 -#restart = True 1.16 +#autorestart = True 1.17 1.18 #============================================================================
2.1 --- a/tools/examples/xmnetbsd Mon Jul 05 08:29:44 2004 +0000 2.2 +++ b/tools/examples/xmnetbsd Mon Jul 05 16:19:14 2004 +0000 2.3 @@ -2,24 +2,23 @@ 2.4 #============================================================================ 2.5 # Python defaults setup for 'xm create'. 2.6 # Edit this file to reflect the configuration of your system. 2.7 -# This file expects the variable 'vmid' to be set. 2.8 #============================================================================ 2.9 2.10 -def config_usage (): 2.11 - print >>sys.stderr,""" 2.12 -The config file '%s' requires the following variable to be defined: 2.13 - vmid -- Numeric identifier for the new domain, used to calculate 2.14 - the VM's IP address and root partition. E.g. -Dvmid=1 2.15 -""" % config_file 2.16 - 2.17 +# Define script variables here. 2.18 +# xm_vars is defined automatically, use xm_vars.var() to define a variable. 2.19 2.20 -try: 2.21 - vmid = int(vmid) # convert to integer 2.22 -except: 2.23 - raise ValueError, "Variable 'vmid' must be an integer" 2.24 +def vmid_check(var, val): 2.25 + val = int(val) 2.26 + if val <= 0: 2.27 + raise ValueError 2.28 + return val 2.29 + 2.30 +xm_vars.var('vmid', 2.31 + use="Virtual machine id. Integer greater than 0.", 2.32 + check=vmid_check) 2.33 2.34 -if vmid <= 0: 2.35 - raise ValueError, "Variable 'vmid' must be greater than 0" 2.36 +# This checks the script variables. 2.37 +xm_vars.check() 2.38 2.39 #---------------------------------------------------------------------------- 2.40 # Kernel image file. 2.41 @@ -97,6 +96,6 @@ extra = "4 VMID=%d bootdev=xennet0" % vm 2.42 #---------------------------------------------------------------------------- 2.43 # Set according to whether you want the domain restarted when it exits. 2.44 # The default is False. 2.45 -#restart = True 2.46 +#autorestart = True 2.47 2.48 #============================================================================
3.1 --- a/tools/python/xen/xend/XendClient.py Mon Jul 05 08:29:44 2004 +0000 3.2 +++ b/tools/python/xen/xend/XendClient.py Mon Jul 05 16:19:14 2004 +0000 3.3 @@ -225,9 +225,10 @@ class Xend: 3.4 return xend_call(self.domainurl(id), 3.5 {'op' : 'pause'}) 3.6 3.7 - def xend_domain_shutdown(self, id): 3.8 + def xend_domain_shutdown(self, id, reason): 3.9 return xend_call(self.domainurl(id), 3.10 - {'op' : 'shutdown'}) 3.11 + {'op' : 'shutdown', 3.12 + 'reason' : reason }) 3.13 3.14 def xend_domain_destroy(self, id): 3.15 return xend_call(self.domainurl(id),
4.1 --- a/tools/python/xen/xend/XendDomain.py Mon Jul 05 08:29:44 2004 +0000 4.2 +++ b/tools/python/xen/xend/XendDomain.py Mon Jul 05 16:19:14 2004 +0000 4.3 @@ -5,8 +5,10 @@ 4.4 Needs to be persistent for one uptime. 4.5 """ 4.6 import sys 4.7 +import traceback 4.8 4.9 from twisted.internet import defer 4.10 +from twisted.internet import reactor 4.11 4.12 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new() 4.13 4.14 @@ -28,10 +30,19 @@ eserver = EventServer.instance() 4.15 class XendDomain: 4.16 """Index of all domains. Singleton. 4.17 """ 4.18 - 4.19 + 4.20 + """Path to domain database.""" 4.21 dbpath = "domain" 4.22 + 4.23 + """Table of domain info indexed by domain id.""" 4.24 domain = {} 4.25 4.26 + """Table of configs for domain restart, indexed by domain id.""" 4.27 + restarts = {} 4.28 + 4.29 + """Table of delayed calls.""" 4.30 + schedule = {} 4.31 + 4.32 def __init__(self): 4.33 self.xconsole = XendConsole.instance() 4.34 # Table of domain info indexed by domain id. 4.35 @@ -49,6 +60,53 @@ class XendDomain: 4.36 print 'XendDomain> virq', val 4.37 self.reap() 4.38 4.39 + def schedule_later(self, _delay, _name, _fn, *args): 4.40 + """Schedule a function to be called later (if not already scheduled). 4.41 + 4.42 + _delay delay in seconds 4.43 + _name schedule name 4.44 + _fn function 4.45 + args arguments 4.46 + """ 4.47 + if self.schedule.get(_name): return 4.48 + self.schedule[_name] = reactor.callLater(_delay, _fn, *args) 4.49 + 4.50 + def schedule_cancel(self, name): 4.51 + """Cancel a scheduled function call. 4.52 + 4.53 + name schedule name to cancel 4.54 + """ 4.55 + callid = self.schedule.get(name) 4.56 + if not callid: 4.57 + return 4.58 + if callid.active(): 4.59 + callid.cancel() 4.60 + del self.schedule[name] 4.61 + 4.62 + def reap_schedule(self, delay=0): 4.63 + """Schedule reap to be called later. 4.64 + 4.65 + delay delay in seconds 4.66 + """ 4.67 + self.schedule_later(delay, 'reap', self.reap) 4.68 + 4.69 + def reap_cancel(self): 4.70 + """Cancel any scheduled reap. 4.71 + """ 4.72 + self.schedule_cancel('reap') 4.73 + 4.74 + def refresh_schedule(self, delay=0): 4.75 + """Schedule refresh to be called later. 4.76 + 4.77 + delay delay in seconds 4.78 + """ 4.79 + self.schedule_later(delay, 'refresh', self.refresh) 4.80 + 4.81 + def refresh_cancel(self): 4.82 + """Cancel any scheduled refresh. 4.83 + """ 4.84 + self.schedule_cancel('refresh') 4.85 + 4.86 def rm_all(self): 4.87 """Remove all domain info. Used after reboot. 4.88 """ 4.89 @@ -145,6 +203,7 @@ class XendDomain: 4.90 """Look for domains that have crashed or stopped. 4.91 Tidy them up. 4.92 """ 4.93 + self.reap_cancel() 4.94 print 'XendDomain>reap>' 4.95 domlist = xc.domain_getinfo() 4.96 casualties = [] 4.97 @@ -158,12 +217,14 @@ class XendDomain: 4.98 for d in casualties: 4.99 id = str(d['dom']) 4.100 print 'XendDomain>reap> died id=', id, d 4.101 - self.domain_destroy(id, refresh=0) 4.102 + self.final_domain_destroy(id) 4.103 print 'XendDomain>reap<' 4.104 4.105 def refresh(self): 4.106 """Refresh domain list from Xen. 4.107 """ 4.108 + self.refresh_cancel() 4.109 + print 'XendDomain>refresh>' 4.110 domlist = xc.domain_getinfo() 4.111 # Index the domlist by id. 4.112 # Add entries for any domains we don't know about. 4.113 @@ -184,7 +245,7 @@ class XendDomain: 4.114 d.update(dominfo) 4.115 else: 4.116 self._delete_domain(d.id) 4.117 - self.reap() 4.118 + self.reap_schedule(1) 4.119 4.120 def refresh_domain(self, id): 4.121 """Refresh information for a single domain. 4.122 @@ -267,21 +328,70 @@ class XendDomain: 4.123 """Shutdown domain (nicely). 4.124 4.125 id domain id 4.126 - reason shutdown type: poweroff, reboot, halt 4.127 + reason shutdown type: poweroff, reboot, suspend, halt 4.128 """ 4.129 dom = int(id) 4.130 if dom <= 0: 4.131 return 0 4.132 + self.domain_restart_schedule(id, reason) 4.133 eserver.inject('xend.domain.shutdown', [id, reason]) 4.134 + if reason == 'halt': 4.135 + reason = 'poweroff' 4.136 val = xend.domain_shutdown(dom, reason) 4.137 - self.refresh() 4.138 + self.refresh_schedule() 4.139 return val 4.140 - 4.141 - def domain_destroy(self, id, refresh=1): 4.142 - """Terminate domain immediately. 4.143 + 4.144 + def domain_restart_schedule(self, id, reason): 4.145 + """Schedule a restart for a domain if it needs one. 4.146 + 4.147 + id domain id 4.148 + reason shutdown reason 4.149 + """ 4.150 + if id in self.restarts: 4.151 + # Don't schedule if already there. 4.152 + return 4.153 + restart = 0 4.154 + if reason in ['poweroff', 'reboot']: 4.155 + dominfo = self.domain.get(id) 4.156 + if dominfo and (dominfo.autorestart or reason == 'reboot'): 4.157 + restart = 1 4.158 + # Clear autorestart flag to avoid multiple restarts. 4.159 + dominfo.autorestart = 0 4.160 + 4.161 + if restart: 4.162 + self.restarts[id] = dominfo.config 4.163 + 4.164 + def domain_restart_cancel(self, id): 4.165 + """Cancel any restart scheduled for a domain. 4.166 4.167 id domain id 4.168 - refresh send a domain destroy event if true 4.169 + """ 4.170 + dominfo = self.domain.get(id) 4.171 + if dominfo: 4.172 + dominfo.autorestart = 0 4.173 + if id in self.restarts: 4.174 + del self.restarts[id] 4.175 + 4.176 + def domain_restarts(self): 4.177 + """Execute any scheduled domain restarts for domains that have gone. 4.178 + """ 4.179 + for id in self.restarts.keys(): 4.180 + if id in self.domain: 4.181 + # Don't execute restart for domains still running. 4.182 + continue 4.183 + config = self.restarts[id] 4.184 + # Remove it from the restarts. 4.185 + del self.restarts[id] 4.186 + try: 4.187 + self.domain_create(config) 4.188 + except: 4.189 + print >>sys.stderr, "XendDomain> Exception restarting domain" 4.190 + traceback.print_exc(sys.stderr) 4.191 + 4.192 + def final_domain_destroy(self, id): 4.193 + """Final destruction of a domain.. 4.194 + 4.195 + id domain id 4.196 """ 4.197 dom = int(id) 4.198 if dom <= 0: 4.199 @@ -292,15 +402,26 @@ class XendDomain: 4.200 val = dominfo.destroy() 4.201 else: 4.202 val = xc.domain_destroy(dom=dom) 4.203 - if refresh: self.refresh() 4.204 return val 4.205 4.206 + def domain_destroy(self, id): 4.207 + """Terminate domain immediately. 4.208 + Camcels any restart for the domain. 4.209 + 4.210 + id domain id 4.211 + """ 4.212 + self.domain_restart_cancel(id) 4.213 + val = self.final_domain_destroy(id) 4.214 + self.refresh_schedule() 4.215 + return val 4.216 + 4.217 def domain_migrate(self, id, dst): 4.218 """Start domain migration. 4.219 4.220 id domain id 4.221 """ 4.222 # Need a cancel too? 4.223 + # Don't forget to cancel restart for it. 4.224 pass 4.225 4.226 def domain_save(self, id, dst, progress=0):
5.1 --- a/tools/python/xen/xend/XendDomainInfo.py Mon Jul 05 08:29:44 2004 +0000 5.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Jul 05 16:19:14 2004 +0000 5.3 @@ -362,6 +362,8 @@ class XendDomainInfo: 5.4 self.state = self.STATE_OK 5.5 #todo: set to migrate info if migrating 5.6 self.migrate = None 5.7 + #Whether to auto-restart 5.8 + self.autorestart = 0 5.9 5.10 def setdom(self, dom): 5.11 self.dom = int(dom) 5.12 @@ -418,6 +420,8 @@ class XendDomainInfo: 5.13 try: 5.14 self.name = sxp.child_value(config, 'name') 5.15 self.memory = int(sxp.child_value(config, 'memory', '128')) 5.16 + if sxp.child(config, 'autorestart', None): 5.17 + self.autorestart = 1 5.18 self.configure_backends() 5.19 image = sxp.child_value(config, 'image') 5.20 image_name = sxp.name(image)
6.1 --- a/tools/python/xen/xend/server/SrvDomain.py Mon Jul 05 08:29:44 2004 +0000 6.2 +++ b/tools/python/xen/xend/server/SrvDomain.py Mon Jul 05 16:19:14 2004 +0000 6.3 @@ -27,7 +27,11 @@ class SrvDomain(SrvDir): 6.4 return val 6.5 6.6 def op_shutdown(self, op, req): 6.7 - val = self.xd.domain_shutdown(self.dom.id) 6.8 + #val = self.xd.domain_shutdown(self.dom.id) 6.9 + fn = FormFn(self.xd.domain_shutdown, 6.10 + [['dom', 'int'], 6.11 + ['reason', 'str']]) 6.12 + val = fn(req.args, {'dom': self.dom.id}) 6.13 req.setResponseCode(202) 6.14 req.setHeader("Location", "%s/.." % req.prePathURL()) 6.15 return val
7.1 --- a/tools/python/xen/xm/create.py Mon Jul 05 08:29:44 2004 +0000 7.2 +++ b/tools/python/xen/xm/create.py Mon Jul 05 16:19:14 2004 +0000 7.3 @@ -101,6 +101,10 @@ gopts.opt('memory', short='m', val='MEMO 7.4 fn=set_value, default=128, 7.5 use="Domain memory in MB.") 7.6 7.7 +gopts.opt('autorestart', 7.8 + fn=set_true, default=0, 7.9 + use="Whether to restart the domain on exit.") 7.10 + 7.11 gopts.opt('blkif', 7.12 fn=set_true, default=0, 7.13 use="Make the domain a block device backend.") 7.14 @@ -271,6 +275,8 @@ def make_config(opts): 7.15 config.append(['backend', ['blkif']]) 7.16 if opts.netif: 7.17 config.append(['backend', ['netif']]) 7.18 + if opts.autorestart: 7.19 + config.append(['autorestart']) 7.20 7.21 configure_image(config, opts) 7.22 config_devs = []
8.1 --- a/tools/python/xen/xm/shutdown.py Mon Jul 05 08:29:44 2004 +0000 8.2 +++ b/tools/python/xen/xm/shutdown.py Mon Jul 05 16:19:14 2004 +0000 8.3 @@ -1,4 +1,5 @@ 8.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 8.5 + 8.6 """Domain shutdown. 8.7 """ 8.8 import string 8.9 @@ -10,7 +11,8 @@ from xen.xm.opts import * 8.10 8.11 gopts = Opts(use="""[options] [DOM] 8.12 8.13 -Shutdown one or more domains gracefully.""") 8.14 +Shutdown one or more domains gracefully. 8.15 +""") 8.16 8.17 gopts.opt('help', short='h', 8.18 fn=set_true, default=0, 8.19 @@ -24,18 +26,22 @@ gopts.opt('wait', short='w', 8.20 fn=set_true, default=0, 8.21 use='Wait for shutdown to complete.') 8.22 8.23 -gopts.opt('norestart', short='n', 8.24 +gopts.opt('halt', short='H', 8.25 fn=set_true, default=0, 8.26 - use='Prevent domain restart.') 8.27 + use='Shutdown without reboot.') 8.28 8.29 -def shutdown(opts, doms, wait): 8.30 +gopts.opt('reboot', short='R', 8.31 + fn=set_true, default=0, 8.32 + use='Shutdown and reboot.') 8.33 + 8.34 +def shutdown(opts, doms, mode, wait): 8.35 def domains(): 8.36 return [ int(a) for a in server.xend_domains() ] 8.37 if doms == None: doms = domains() 8.38 if 0 in doms: 8.39 doms.remove(0) 8.40 for d in doms: 8.41 - server.xend_domain_shutdown(d) 8.42 + server.xend_domain_shutdown(d, mode) 8.43 if wait: 8.44 while doms: 8.45 alive = domains() 8.46 @@ -49,6 +55,21 @@ def shutdown(opts, doms, wait): 8.47 time.sleep(1) 8.48 opts.info("All domains terminated") 8.49 8.50 +def shutdown_mode(opts): 8.51 + mode = 'poweroff' 8.52 + if opts.vals.wait: 8.53 + mode = 'halt' 8.54 + if opts.vals.reboot: 8.55 + opts.err("Can't specify wait and reboot") 8.56 + else: 8.57 + if opts.vals.halt and opts.vals.reboot: 8.58 + opts.err("Can't specify halt and reboot") 8.59 + if opts.vals.halt: 8.60 + mode = 'halt' 8.61 + elif opts.vals.reboot: 8.62 + mode = 'reboot' 8.63 + return mode 8.64 + 8.65 def main_all(opts, args): 8.66 shutdown(opts, None, opts.vals.wait) 8.67 8.68 @@ -59,7 +80,9 @@ def main_dom(opts, args): 8.69 domid = int(dom) 8.70 except: 8.71 opts.err('Invalid domain: ' + dom) 8.72 - shutdown(opts, [ domid ], opts.vals.wait) 8.73 + 8.74 + mode = shutdown_mode(opts) 8.75 + shutdown(opts, [ domid ], mode, opts.vals.wait) 8.76 8.77 def main(argv): 8.78 opts = gopts