mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.1081.1.1 (40f552eaWV4viomXWEuk8dzfLHid7g)
Change to new restart model.
This commit is contained in:
1 parent
a5af4e1ea5
commit
c0aa821f0d
10 files changed
+138
-65
No files matched your search
@@ -256,9 +256,10 @@ class Xend:
|
||||
{'op' : 'shutdown',
|
||||
'reason' : reason })
|
||||
|
||||
def xend_domain_destroy(self, id):
|
||||
def xend_domain_destroy(self, id, reason):
|
||||
return xend_call(self.domainurl(id),
|
||||
{'op' : 'destroy' })
|
||||
{'op' : 'destroy',
|
||||
'reason' : reason })
|
||||
|
||||
def xend_domain_save(self, id, filename):
|
||||
return xend_call(self.domainurl(id),
|
||||
|
||||
@@ -378,9 +378,9 @@ class XendDomain:
|
||||
|
||||
def domain_shutdown(self, id, reason='poweroff'):
|
||||
"""Shutdown domain (nicely).
|
||||
- poweroff: domain will restart if has autorestart set.
|
||||
- reboot: domain will restart.
|
||||
- halt: domain will not restart (even if has autorestart set).
|
||||
- poweroff: restart according to exit code and restart mode
|
||||
- reboot: restart on exit
|
||||
- halt: do not restart
|
||||
|
||||
Returns immediately.
|
||||
|
||||
@@ -388,12 +388,13 @@ class XendDomain:
|
||||
@param reason: shutdown type: poweroff, reboot, suspend, halt
|
||||
"""
|
||||
dom = int(id)
|
||||
id = str(id)
|
||||
if dom <= 0:
|
||||
return 0
|
||||
if reason == 'halt':
|
||||
self.domain_restart_cancel(id)
|
||||
else:
|
||||
self.domain_restart_schedule(id, reason)
|
||||
self.domain_restart_schedule(id, reason, set=1)
|
||||
eserver.inject('xend.domain.shutdown', [id, reason])
|
||||
if reason == 'halt':
|
||||
reason = 'poweroff'
|
||||
@@ -401,21 +402,24 @@ class XendDomain:
|
||||
self.refresh_schedule()
|
||||
return val
|
||||
|
||||
def domain_restart_schedule(self, id, reason):
|
||||
def domain_restart_schedule(self, id, reason, set=0):
|
||||
"""Schedule a restart for a domain if it needs one.
|
||||
|
||||
@param id: domain id
|
||||
@param reason: shutdown reason
|
||||
"""
|
||||
print 'domain_restart_schedule>', id, reason, set
|
||||
dominfo = self.domain.get(id)
|
||||
if not dominfo or id in self.restarts:
|
||||
# Don't schedule if unknown or already there.
|
||||
if not dominfo:
|
||||
return
|
||||
restart = ((reason == 'reboot') or
|
||||
(reason == 'poweroff' and dominfo.autorestart))
|
||||
if id in self.restarts:
|
||||
return
|
||||
if set and reason == 'reboot':
|
||||
dominfo.restart_mode = XendDomainInfo.RESTART_ALWAYS
|
||||
restart = dominfo.restart_needed(reason)
|
||||
if restart:
|
||||
# Clear autorestart flag to avoid multiple restarts.
|
||||
dominfo.autorestart = 0
|
||||
# Avoid multiple restarts.
|
||||
dominfo.restart_mode = XendDomainInfo.RESTART_NEVER
|
||||
self.restarts[id] = dominfo.config
|
||||
print 'Scheduling restart for domain:', id, dominfo.name
|
||||
self.domain_restarts_schedule()
|
||||
@@ -427,7 +431,7 @@ class XendDomain:
|
||||
"""
|
||||
dominfo = self.domain.get(id)
|
||||
if dominfo:
|
||||
dominfo.autorestart = 0
|
||||
dominfo.restart_mode = XendDomainInfo.RESTART_NEVER
|
||||
if id in self.restarts:
|
||||
del self.restarts[id]
|
||||
|
||||
@@ -474,13 +478,18 @@ class XendDomain:
|
||||
val = xc.domain_destroy(dom=dom)
|
||||
return val
|
||||
|
||||
def domain_destroy(self, id):
|
||||
def domain_destroy(self, id, reason='halt'):
|
||||
"""Terminate domain immediately.
|
||||
Cancels any restart for the domain.
|
||||
- halt: cancel any restart for the domain
|
||||
- reboot schedule a restart for the domain
|
||||
|
||||
@param id: domain id
|
||||
"""
|
||||
self.domain_restart_cancel(id)
|
||||
id = str(id)
|
||||
if reason == 'halt':
|
||||
self.domain_restart_cancel(id)
|
||||
elif reason == 'reboot':
|
||||
self.domain_restart_schedule(id, reason, set=1)
|
||||
val = self.final_domain_destroy(id)
|
||||
self.refresh_schedule()
|
||||
return val
|
||||
|
||||
@@ -50,6 +50,16 @@ shutdown_reasons = {
|
||||
DOMAIN_REBOOT : "reboot",
|
||||
DOMAIN_SUSPEND : "suspend" }
|
||||
|
||||
RESTART_ALWAYS = 'always'
|
||||
RESTART_ONREBOOT = 'onreboot'
|
||||
RESTART_NEVER = 'never'
|
||||
|
||||
restart_modes = [
|
||||
RESTART_ALWAYS,
|
||||
RESTART_ONREBOOT,
|
||||
RESTART_NEVER,
|
||||
]
|
||||
|
||||
def shutdown_reason(code):
|
||||
"""Get a shutdown reason from a code.
|
||||
|
||||
@@ -117,7 +127,12 @@ def lookup_disk_uname(uname):
|
||||
def make_disk(dom, uname, dev, mode, recreate=0):
|
||||
"""Create a virtual disk device for a domain.
|
||||
|
||||
@returns Deferred
|
||||
@param dom: domain id
|
||||
@param uname: device to export
|
||||
@param dev: device name in domain
|
||||
@param mode: read/write mode
|
||||
@param recreate: recreate flag (after xend restart)
|
||||
@return: deferred
|
||||
"""
|
||||
segments = lookup_disk_uname(uname)
|
||||
if not segments:
|
||||
@@ -234,7 +249,6 @@ def vm_create(config):
|
||||
returns Deferred
|
||||
raises VmError for invalid configuration
|
||||
"""
|
||||
print 'vm_create>'
|
||||
vm = XendDomainInfo()
|
||||
return vm.construct(config)
|
||||
|
||||
@@ -289,28 +303,21 @@ def append_deferred(dlist, v):
|
||||
|
||||
def _vm_configure1(val, vm):
|
||||
d = vm.create_devices()
|
||||
#print '_vm_configure1> made devices...'
|
||||
def cbok(x):
|
||||
#print '_vm_configure1> cbok', x
|
||||
return x
|
||||
d.addCallback(cbok)
|
||||
d.addCallback(_vm_configure2, vm)
|
||||
#print '_vm_configure1<'
|
||||
return d
|
||||
|
||||
def _vm_configure2(val, vm):
|
||||
#print '>callback _vm_configure2...'
|
||||
d = vm.configure_fields()
|
||||
def cbok(results):
|
||||
#print '_vm_configure2> cbok', results
|
||||
return vm
|
||||
def cberr(err):
|
||||
#print '_vm_configure2> cberr', err
|
||||
vm.destroy()
|
||||
return err
|
||||
d.addCallback(cbok)
|
||||
d.addErrback(cberr)
|
||||
#print '<_vm_configure2'
|
||||
return d
|
||||
|
||||
class XendDomainInfo:
|
||||
@@ -341,7 +348,7 @@ class XendDomainInfo:
|
||||
#todo: set to migrate info if migrating
|
||||
self.migrate = None
|
||||
#Whether to auto-restart
|
||||
self.autorestart = 0
|
||||
self.restart_mode = RESTART_ONREBOOT
|
||||
|
||||
def setdom(self, dom):
|
||||
self.dom = int(dom)
|
||||
@@ -381,8 +388,7 @@ class XendDomainInfo:
|
||||
state = run + block + stop + susp + crash
|
||||
sxpr.append(['state', state])
|
||||
if self.info['shutdown']:
|
||||
reasons = ["poweroff", "reboot", "suspend"]
|
||||
reason = reasons[self.info['shutdown_reason']]
|
||||
reason = shutdown_reason(self.info['shutdown_reason'])
|
||||
sxpr.append(['shutdown_reason', reason])
|
||||
sxpr.append(['cpu', self.info['cpu']])
|
||||
sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
|
||||
@@ -398,8 +404,7 @@ 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_restart()
|
||||
self.configure_backends()
|
||||
image = sxp.child_value(config, 'image')
|
||||
if image is None:
|
||||
@@ -413,7 +418,6 @@ class XendDomainInfo:
|
||||
image_handler(self, image)
|
||||
deferred = self.configure()
|
||||
def cbok(x):
|
||||
print 'vm_create> cbok', x
|
||||
return x
|
||||
def cberr(err):
|
||||
self.destroy()
|
||||
@@ -424,7 +428,6 @@ class XendDomainInfo:
|
||||
# Catch errors, cleanup and re-raise.
|
||||
self.destroy()
|
||||
raise
|
||||
print 'vm_create<'
|
||||
return deferred
|
||||
|
||||
def config_devices(self, name):
|
||||
@@ -514,7 +517,6 @@ class XendDomainInfo:
|
||||
def cleanup(self):
|
||||
"""Cleanup vm resources: release devices.
|
||||
"""
|
||||
print 'cleanup>', self.dom
|
||||
self.state = self.STATE_TERMINATED
|
||||
self.release_devices()
|
||||
|
||||
@@ -526,7 +528,6 @@ class XendDomainInfo:
|
||||
def release_devices(self):
|
||||
"""Release all vm devices.
|
||||
"""
|
||||
print 'release_devices>', self.dom
|
||||
self.release_vifs()
|
||||
self.release_vbds()
|
||||
self.devices = {}
|
||||
@@ -534,7 +535,6 @@ class XendDomainInfo:
|
||||
def release_vifs(self):
|
||||
"""Release vm virtual network devices (vifs).
|
||||
"""
|
||||
print 'release_vifs>', self.dom
|
||||
if self.dom is None: return
|
||||
ctrl = xend.netif_get(self.dom)
|
||||
if ctrl:
|
||||
@@ -543,7 +543,6 @@ class XendDomainInfo:
|
||||
def release_vbds(self):
|
||||
"""Release vm virtual block devices (vbds).
|
||||
"""
|
||||
print 'release_vbds>', self.dom
|
||||
if self.dom is None: return
|
||||
ctrl = xend.blkif_get(self.dom)
|
||||
if ctrl:
|
||||
@@ -574,7 +573,7 @@ class XendDomainInfo:
|
||||
memory = self.memory
|
||||
name = self.name
|
||||
cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
|
||||
print 'init_domain>', memory, name, cpu
|
||||
#print 'init_domain>', memory, name, cpu
|
||||
dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
|
||||
if dom <= 0:
|
||||
raise VmError('Creating domain failed: name=%s memory=%d'
|
||||
@@ -589,7 +588,7 @@ class XendDomainInfo:
|
||||
print 'Warning: kernel cmdline too long'
|
||||
dom = self.dom
|
||||
buildfn = getattr(xc, '%s_build' % ostype)
|
||||
print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
|
||||
#print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
|
||||
flags = 0
|
||||
if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
|
||||
if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
|
||||
@@ -612,15 +611,12 @@ class XendDomainInfo:
|
||||
cmdline kernel commandline
|
||||
vifs_n number of network interfaces
|
||||
"""
|
||||
print 'create_domain>', ostype, kernel
|
||||
if not self.recreate:
|
||||
if not os.path.isfile(kernel):
|
||||
raise VmError('Kernel image does not exist: %s' % kernel)
|
||||
if ramdisk and not os.path.isfile(ramdisk):
|
||||
raise VmError('Kernel ramdisk does not exist: %s' % ramdisk)
|
||||
print 'create-domain> init_domain...'
|
||||
self.init_domain()
|
||||
print 'create_domain>', 'dom=', self.dom
|
||||
self.console = xendConsole.console_create(self.dom)
|
||||
self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
|
||||
self.image = kernel
|
||||
@@ -633,7 +629,6 @@ class XendDomainInfo:
|
||||
returns Deferred
|
||||
raises VmError for invalid devices
|
||||
"""
|
||||
print '>create_devices'
|
||||
dlist = []
|
||||
devices = sxp.children(self.config, 'device')
|
||||
index = {}
|
||||
@@ -650,7 +645,6 @@ class XendDomainInfo:
|
||||
append_deferred(dlist, v)
|
||||
index[dev_name] = dev_index + 1
|
||||
deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
|
||||
print '<create_devices'
|
||||
return deferred
|
||||
|
||||
def device_create(self, dev_config):
|
||||
@@ -686,6 +680,21 @@ class XendDomainInfo:
|
||||
self.config.remove(['device', dev_config])
|
||||
dev.destroy()
|
||||
|
||||
def configure_restart(self):
|
||||
r = sxp.child_value(self.config, 'restart', RESTART_ONREBOOT)
|
||||
if r not in restart_modes:
|
||||
raise VmError('invalid restart mode: ' + str(r))
|
||||
self.restart_mode = r;
|
||||
|
||||
def restart_needed(self, reason):
|
||||
if self.restart_mode == RESTART_NEVER:
|
||||
return 0
|
||||
if self.restart_mode == RESTART_ALWAYS:
|
||||
return 1
|
||||
if self.restart_mode == RESTART_ONREBOOT:
|
||||
return reason == 'reboot'
|
||||
return 0
|
||||
|
||||
def configure_backends(self):
|
||||
"""Set configuration flags if the vm is a backend for netif of blkif.
|
||||
"""
|
||||
@@ -807,7 +816,7 @@ def vm_image_netbsd(vm, image):
|
||||
args = sxp.child_value(image, "args")
|
||||
if args:
|
||||
cmdline += " " + args
|
||||
ramdisk = sxp.child_value(image, "ramdisk")
|
||||
ramdisk = sxp.child_value(image, "ramdisk", '')
|
||||
vifs = vm.config_devices("vif")
|
||||
vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
|
||||
return vm
|
||||
@@ -830,7 +839,6 @@ def vm_dev_vif(vm, val, index):
|
||||
dev = xend.netif_dev(vm.dom, vif)
|
||||
dev.vifctl('up', vmname=vm.name)
|
||||
vm.add_device('vif', dev)
|
||||
print 'vm_dev_vif> created', dev
|
||||
return id
|
||||
defer.addCallback(fn)
|
||||
return defer
|
||||
|
||||
@@ -50,7 +50,10 @@ class SrvDomain(SrvDir):
|
||||
return val
|
||||
|
||||
def op_destroy(self, op, req):
|
||||
val = self.xd.domain_destroy(self.dom.id)
|
||||
fn = FormFn(self.xd.domain_destroy,
|
||||
[['dom', 'int'],
|
||||
['reason', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
req.setHeader("Location", "%s/.." % req.prePathURL())
|
||||
return val
|
||||
|
||||
@@ -220,7 +223,12 @@ class SrvDomain(SrvDir):
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
req.write('<input type="submit" name="op" value="unpause">')
|
||||
req.write('<input type="submit" name="op" value="pause">')
|
||||
req.write('</form>')
|
||||
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
req.write('<input type="submit" name="op" value="destroy">')
|
||||
req.write('<input type="radio" name="reason" value="halt" checked>Halt')
|
||||
req.write('<input type="radio" name="reason" value="reboot">Reboot')
|
||||
req.write('</form>')
|
||||
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
|
||||
@@ -97,9 +97,13 @@ gopts.var('memory', val='MEMORY',
|
||||
fn=set_value, default=128,
|
||||
use="Domain memory in MB.")
|
||||
|
||||
gopts.var('autorestart', val='no|yes',
|
||||
fn=set_bool, default=0,
|
||||
use="Whether to restart the domain on exit.")
|
||||
gopts.var('restart', val='onreboot|always|never',
|
||||
fn=set_value, default=None,
|
||||
use="""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('blkif', val='no|yes',
|
||||
fn=set_bool, default=0,
|
||||
@@ -294,8 +298,8 @@ def make_config(vals):
|
||||
config.append(['backend', ['blkif']])
|
||||
if vals.netif:
|
||||
config.append(['backend', ['netif']])
|
||||
if vals.autorestart:
|
||||
config.append(['autorestart'])
|
||||
if vals.restart:
|
||||
config.append(['restart', vals.restart])
|
||||
|
||||
configure_image(config, vals)
|
||||
config_devs = []
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
"""Destroy a domain.
|
||||
"""
|
||||
|
||||
from xen.xend.XendClient import server
|
||||
from xen.xm.opts import *
|
||||
|
||||
gopts = Opts(use="""[options] [DOM]
|
||||
|
||||
Destroy a domain, optionally restarting it.
|
||||
""")
|
||||
|
||||
gopts.opt('help', short='h',
|
||||
fn=set_true, default=0,
|
||||
use="Print this help.")
|
||||
|
||||
gopts.opt('reboot', short='R',
|
||||
fn=set_true, default=0,
|
||||
use='Destroy and restart.')
|
||||
|
||||
def main(argv):
|
||||
opts = gopts
|
||||
args = opts.parse(argv)
|
||||
if opts.vals.help:
|
||||
opts.usage()
|
||||
return
|
||||
if len(args) < 1: opts.err('Missing domain')
|
||||
dom = args[0]
|
||||
try:
|
||||
domid = int(dom)
|
||||
except:
|
||||
opts.err('Invalid domain: ' + dom)
|
||||
if opts.vals.reboot:
|
||||
mode = 'reboot'
|
||||
else:
|
||||
mode = 'halt'
|
||||
server.xend_domain_destroy(domid, mode)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from xen.xend import PrettyPrint
|
||||
from xen.xend import sxp
|
||||
from xen.xend.XendClient import XendError, server
|
||||
from xen.xend.XendClient import main as xend_client_main
|
||||
from xen.xm import create, shutdown
|
||||
from xen.xm import create, destroy, shutdown
|
||||
|
||||
class Prog:
|
||||
"""Base class for sub-programs.
|
||||
@@ -268,13 +268,10 @@ class ProgDestroy(Prog):
|
||||
info = """Terminate a domain immediately."""
|
||||
|
||||
def help(self, args):
|
||||
print args[0], 'DOM'
|
||||
print '\nTerminate domain DOM immediately.'
|
||||
destroy.main([args[0], '-h'])
|
||||
|
||||
def main(self, args):
|
||||
if len(args) < 2: self.err("%s: Missing domain" % args[0])
|
||||
dom = args[1]
|
||||
server.xend_domain_destroy(dom)
|
||||
destroy.main(args)
|
||||
|
||||
xm.prog(ProgDestroy)
|
||||
|
||||
|
||||