ia64/xen-unstable

view tools/python/xen/xend/image.py @ 17117:9dd235d6174d

Fix restore of saved image containing rtc_timeoffset

Saved images contain rtc_timeoffset as a string value, resulting in a
TypeError exception when calling xc.domain_set_time_offset() on
restore. Cast rtc_timeoffset to int before calling
xc.domain_set_time_offset().

Signed-off-by: Jim Fehlig <jfehlig@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Feb 26 14:35:39 2008 +0000 (2008-02-26)
parents c6eeb71a85cf
children e44c6b67a483
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2005 Mike Wray <mike.wray@hp.com>
16 # Copyright (C) 2005-2007 XenSource Ltd
17 #============================================================================
20 import os, os.path, string
21 import re
22 import math
23 import time
24 import signal
26 import xen.lowlevel.xc
27 from xen.xend.XendConstants import *
28 from xen.xend.XendError import VmError, XendError, HVMRequired
29 from xen.xend.XendLogging import log
30 from xen.xend.XendOptions import instance as xenopts
31 from xen.xend.xenstore.xstransact import xstransact
32 from xen.xend.xenstore.xswatch import xswatch
33 from xen.xend import arch
34 from xen.xend import XendOptions
36 xc = xen.lowlevel.xc.xc()
38 MAX_GUEST_CMDLINE = 1024
41 def create(vm, vmConfig):
42 """Create an image handler for a vm.
44 @return ImageHandler instance
45 """
46 return findImageHandlerClass(vmConfig)(vm, vmConfig)
49 class ImageHandler:
50 """Abstract base class for image handlers.
52 createImage() is called to configure and build the domain from its
53 kernel image and ramdisk etc.
55 The method buildDomain() is used to build the domain, and must be
56 defined in a subclass. Usually this is the only method that needs
57 defining in a subclass.
59 The method createDeviceModel() is called to create the domain device
60 model.
62 The method destroyDeviceModel() is called to reap the device model
63 """
65 ostype = None
68 def __init__(self, vm, vmConfig):
69 self.vm = vm
71 self.bootloader = False
72 self.kernel = None
73 self.ramdisk = None
74 self.cmdline = None
76 self.configure(vmConfig)
78 def configure(self, vmConfig):
79 """Config actions common to all unix-like domains."""
80 if '_temp_using_bootloader' in vmConfig:
81 self.bootloader = True
82 self.kernel = vmConfig['_temp_kernel']
83 self.cmdline = vmConfig['_temp_args']
84 self.ramdisk = vmConfig['_temp_ramdisk']
85 else:
86 self.kernel = vmConfig['PV_kernel']
87 self.cmdline = vmConfig['PV_args']
88 self.ramdisk = vmConfig['PV_ramdisk']
89 self.vm.storeVm(("image/ostype", self.ostype),
90 ("image/kernel", self.kernel),
91 ("image/cmdline", self.cmdline),
92 ("image/ramdisk", self.ramdisk))
94 self.device_model = vmConfig['platform'].get('device_model')
96 self.display = vmConfig['platform'].get('display')
97 self.xauthority = vmConfig['platform'].get('xauthority')
98 self.vncconsole = vmConfig['platform'].get('vncconsole')
99 self.dmargs = self.parseDeviceModelArgs(vmConfig)
100 self.pid = None
104 def cleanupBootloading(self):
105 if self.bootloader:
106 self.unlink(self.kernel)
107 self.unlink(self.ramdisk)
110 def unlink(self, f):
111 if not f: return
112 try:
113 os.unlink(f)
114 except OSError, ex:
115 log.warning("error removing bootloader file '%s': %s", f, ex)
118 def createImage(self):
119 """Entry point to create domain memory image.
120 Override in subclass if needed.
121 """
122 return self.createDomain()
125 def createDomain(self):
126 """Build the domain boot image.
127 """
128 # Set params and call buildDomain().
130 if self.kernel and not os.path.isfile(self.kernel):
131 raise VmError('Kernel image does not exist: %s' % self.kernel)
132 if self.ramdisk and not os.path.isfile(self.ramdisk):
133 raise VmError('Kernel ramdisk does not exist: %s' % self.ramdisk)
134 if len(self.cmdline) >= MAX_GUEST_CMDLINE:
135 log.warning('kernel cmdline too long, domain %d',
136 self.vm.getDomid())
138 log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype,
139 self.vm.getDomid(), self.vm.getVCpuCount())
141 result = self.buildDomain()
143 if isinstance(result, dict):
144 return result
145 else:
146 raise VmError('Building domain failed: ostype=%s dom=%d err=%s'
147 % (self.ostype, self.vm.getDomid(), str(result)))
149 def getRequiredAvailableMemory(self, mem_kb):
150 """@param mem_kb The configured maxmem or memory, in KiB.
151 @return The corresponding required amount of memory for the domain,
152 also in KiB. This is normally the given mem_kb, but architecture- or
153 image-specific code may override this to add headroom where
154 necessary."""
155 return mem_kb
157 def getRequiredInitialReservation(self):
158 """@param mem_kb The configured memory, in KiB.
159 @return The corresponding required amount of memory to be free, also
160 in KiB. This is normally the same as getRequiredAvailableMemory, but
161 architecture- or image-specific code may override this to
162 add headroom where necessary."""
163 return self.getRequiredAvailableMemory(self.vm.getMemoryTarget())
165 def getRequiredMaximumReservation(self):
166 """@param mem_kb The maximum possible memory, in KiB.
167 @return The corresponding required amount of memory to be free, also
168 in KiB. This is normally the same as getRequiredAvailableMemory, but
169 architecture- or image-specific code may override this to
170 add headroom where necessary."""
171 return self.getRequiredAvailableMemory(self.vm.getMemoryMaximum())
173 def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
174 """@param shadow_mem_kb The configured shadow memory, in KiB.
175 @param maxmem_kb The configured maxmem, in KiB.
176 @return The corresponding required amount of shadow memory, also in
177 KiB."""
178 # PV domains don't need any shadow memory
179 return 0
181 def buildDomain(self):
182 """Build the domain. Define in subclass."""
183 raise NotImplementedError()
185 # Return a list of cmd line args to the device models based on the
186 # xm config file
187 def parseDeviceModelArgs(self, vmConfig):
188 ret = ["-domain-name", str(self.vm.info['name_label'])]
190 # Tell QEMU how large the guest's memory allocation is
191 # to help it when loading the initrd (if neccessary)
192 ret += ["-m", str(self.getRequiredInitialReservation() / 1024)]
194 # Find RFB console device, and if it exists, make QEMU enable
195 # the VNC console.
196 if int(vmConfig['platform'].get('nographic', 0)) != 0:
197 # skip vnc init if nographic is set
198 ret.append('-nographic')
199 return ret
201 vnc_config = {}
202 has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
203 has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
204 for dev_uuid in vmConfig['console_refs']:
205 dev_type, dev_info = vmConfig['devices'][dev_uuid]
206 if dev_type == 'vfb':
207 vfb_type = dev_info.get('type', {})
208 if vfb_type == 'sdl':
209 self.display = dev_info.get('display', {})
210 self.xauthority = dev_info.get('xauthority', {})
211 has_sdl = True
212 else:
213 vnc_config = dev_info.get('other_config', {})
214 has_vnc = True
215 break
217 keymap = vmConfig['platform'].get("keymap")
218 if keymap:
219 ret.append("-k")
220 ret.append(keymap)
222 if has_vnc:
223 if not vnc_config:
224 for key in ('vncunused', 'vnclisten', 'vncdisplay',
225 'vncpasswd'):
226 if key in vmConfig['platform']:
227 vnc_config[key] = vmConfig['platform'][key]
228 if vnc_config.has_key("vncpasswd"):
229 passwd = vnc_config["vncpasswd"]
230 else:
231 passwd = XendOptions.instance().get_vncpasswd_default()
232 vncopts = ""
233 if passwd:
234 self.vm.storeVm("vncpasswd", passwd)
235 self.vm.permissionsVm("vncpasswd", { 'dom': self.vm.getDomid(), 'read': True } )
236 vncopts = vncopts + ",password"
237 log.debug("Stored a VNC password for vfb access")
238 else:
239 log.debug("No VNC passwd configured for vfb access")
241 if XendOptions.instance().get_vnc_tls():
242 vncx509certdir = XendOptions.instance().get_vnc_x509_cert_dir()
243 vncx509verify = XendOptions.instance().get_vnc_x509_verify()
245 if not os.path.exists(vncx509certdir):
246 raise VmError("VNC x509 certificate dir %s does not exist" % vncx509certdir)
248 if vncx509verify:
249 vncopts = vncopts + ",tls,x509verify=%s" % vncx509certdir
250 else:
251 vncopts = vncopts + ",tls,x509=%s" % vncx509certdir
254 vnclisten = vnc_config.get('vnclisten',
255 XendOptions.instance().get_vnclisten_address())
256 vncdisplay = vnc_config.get('vncdisplay', 0)
257 ret.append('-vnc')
258 ret.append("%s:%s%s" % (vnclisten, vncdisplay, vncopts))
260 if vnc_config.get('vncunused', 0):
261 ret.append('-vncunused')
263 elif has_sdl:
264 # SDL is default in QEMU.
265 pass
266 else:
267 ret.append('-nographic')
269 if int(vmConfig['platform'].get('monitor', 0)) != 0:
270 ret = ret + ['-monitor', 'vc']
271 return ret
273 def getDeviceModelArgs(self, restore = False):
274 args = [self.device_model]
275 args = args + ([ "-d", "%d" % self.vm.getDomid() ])
276 args = args + self.dmargs
277 return args
279 def createDeviceModel(self, restore = False):
280 if self.device_model is None:
281 return
282 if self.pid:
283 return
284 # Execute device model.
285 #todo: Error handling
286 args = self.getDeviceModelArgs(restore)
287 env = dict(os.environ)
288 if self.display:
289 env['DISPLAY'] = self.display
290 if self.xauthority:
291 env['XAUTHORITY'] = self.xauthority
292 if self.vncconsole:
293 args = args + ([ "-vncviewer" ])
294 xstransact.Mkdir("/local/domain/0/device-model/%i" % self.vm.getDomid())
295 xstransact.SetPermissions("/local/domain/0/device-model/%i" % self.vm.getDomid(),
296 { 'dom': self.vm.getDomid(), 'read': True, 'write': True })
297 log.info("spawning device models: %s %s", self.device_model, args)
298 # keep track of pid and spawned options to kill it later
299 self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
300 self.vm.storeDom("image/device-model-pid", self.pid)
301 log.info("device model pid: %d", self.pid)
303 def signalDeviceModel(self, cmd, ret, par = None):
304 if self.device_model is None:
305 return
306 # Signal the device model to for action
307 if cmd is '' or ret is '':
308 raise VmError('need valid command and result when signal device model')
310 orig_state = xstransact.Read("/local/domain/0/device-model/%i/state"
311 % self.vm.getDomid())
313 if par is not None:
314 xstransact.Store("/local/domain/0/device-model/%i"
315 % self.vm.getDomid(), ('parameter', par))
317 xstransact.Store("/local/domain/0/device-model/%i"
318 % self.vm.getDomid(), ('command', cmd))
319 # Wait for confirmation. Could do this with a watch but we'd
320 # still end up spinning here waiting for the watch to fire.
321 state = ''
322 count = 0
323 while state != ret:
324 state = xstransact.Read("/local/domain/0/device-model/%i/state"
325 % self.vm.getDomid())
326 time.sleep(0.1)
327 count += 1
328 if count > 100:
329 raise VmError('Timed out waiting for device model action')
331 #resotre orig state
332 xstransact.Store("/local/domain/0/device-model/%i"
333 % self.vm.getDomid(), ('state', orig_state))
334 log.info("signalDeviceModel:restore dm state to %s", orig_state)
336 def saveDeviceModel(self):
337 # Signal the device model to pause itself and save its state
338 self.signalDeviceModel('save', 'paused')
340 def resumeDeviceModel(self):
341 if self.device_model is None:
342 return
343 # Signal the device model to resume activity after pausing to save.
344 xstransact.Store("/local/domain/0/device-model/%i"
345 % self.vm.getDomid(), ('command', 'continue'))
347 def recreate(self):
348 if self.device_model is None:
349 return
350 self.pid = self.vm.gatherDom(('image/device-model-pid', int))
352 def destroyDeviceModel(self):
353 if self.device_model is None:
354 return
355 if self.pid:
356 try:
357 os.kill(self.pid, signal.SIGHUP)
358 except OSError, exn:
359 log.exception(exn)
360 try:
361 # Try to reap the child every 100ms for 10s. Then SIGKILL it.
362 for i in xrange(100):
363 (p, rv) = os.waitpid(self.pid, os.WNOHANG)
364 if p == self.pid:
365 break
366 time.sleep(0.1)
367 else:
368 log.warning("DeviceModel %d took more than 10s "
369 "to terminate: sending SIGKILL" % self.pid)
370 os.kill(self.pid, signal.SIGKILL)
371 os.waitpid(self.pid, 0)
372 except OSError, exn:
373 # This is expected if Xend has been restarted within the
374 # life of this domain. In this case, we can kill the process,
375 # but we can't wait for it because it's not our child.
376 # We just make really sure it's going away (SIGKILL) first.
377 os.kill(self.pid, signal.SIGKILL)
378 self.pid = None
379 state = xstransact.Remove("/local/domain/0/device-model/%i"
380 % self.vm.getDomid())
383 class LinuxImageHandler(ImageHandler):
385 ostype = "linux"
386 flags = 0
387 vhpt = 0
389 def configure(self, vmConfig):
390 ImageHandler.configure(self, vmConfig)
391 rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
392 if rtc_timeoffset is not None:
393 xc.domain_set_time_offset(self.vm.getDomid(), int(rtc_timeoffset))
395 def buildDomain(self):
396 store_evtchn = self.vm.getStorePort()
397 console_evtchn = self.vm.getConsolePort()
399 mem_mb = self.getRequiredInitialReservation() / 1024
401 log.debug("domid = %d", self.vm.getDomid())
402 log.debug("memsize = %d", mem_mb)
403 log.debug("image = %s", self.kernel)
404 log.debug("store_evtchn = %d", store_evtchn)
405 log.debug("console_evtchn = %d", console_evtchn)
406 log.debug("cmdline = %s", self.cmdline)
407 log.debug("ramdisk = %s", self.ramdisk)
408 log.debug("vcpus = %d", self.vm.getVCpuCount())
409 log.debug("features = %s", self.vm.getFeatures())
410 if arch.type == "ia64":
411 log.debug("vhpt = %d", self.flags)
413 return xc.linux_build(domid = self.vm.getDomid(),
414 memsize = mem_mb,
415 image = self.kernel,
416 store_evtchn = store_evtchn,
417 console_evtchn = console_evtchn,
418 cmdline = self.cmdline,
419 ramdisk = self.ramdisk,
420 features = self.vm.getFeatures(),
421 flags = self.flags,
422 vhpt = self.vhpt)
424 def parseDeviceModelArgs(self, vmConfig):
425 ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
426 # Equivalent to old xenconsoled behaviour. Should make
427 # it configurable in future
428 ret = ret + ["-serial", "pty"]
429 return ret
431 def getDeviceModelArgs(self, restore = False):
432 args = ImageHandler.getDeviceModelArgs(self, restore)
433 args = args + ([ "-M", "xenpv"])
434 return args
437 class PPC_LinuxImageHandler(LinuxImageHandler):
439 ostype = "linux"
441 def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
442 """@param shadow_mem_kb The configured shadow memory, in KiB.
443 @param maxmem_kb The configured maxmem, in KiB.
444 @return The corresponding required amount of shadow memory, also in
445 KiB.
446 PowerPC currently uses "shadow memory" to refer to the hash table."""
447 return max(maxmem_kb / 64, shadow_mem_kb)
451 class HVMImageHandler(ImageHandler):
453 ostype = "hvm"
455 def __init__(self, vm, vmConfig):
456 ImageHandler.__init__(self, vm, vmConfig)
457 self.shutdownWatch = None
458 self.rebootFeatureWatch = None
460 def configure(self, vmConfig):
461 ImageHandler.configure(self, vmConfig)
463 self.loader = vmConfig['platform'].get('loader')
465 info = xc.xeninfo()
466 if 'hvm' not in info['xen_caps']:
467 raise HVMRequired()
469 rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
471 self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
472 ("image/device-model", self.device_model),
473 ("image/display", self.display))
474 self.vm.permissionsVm("image/dmargs", { 'dom': self.vm.getDomid(), 'read': True } )
475 self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
476 self.vm.permissionsVm("rtc/timeoffset", { 'dom': self.vm.getDomid(), 'read': True } )
478 self.apic = int(vmConfig['platform'].get('apic', 0))
479 self.acpi = int(vmConfig['platform'].get('acpi', 0))
480 self.guest_os_type = vmConfig['platform'].get('guest_os_type')
482 # Return a list of cmd line args to the device models based on the
483 # xm config file
484 def parseDeviceModelArgs(self, vmConfig):
485 ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
486 ret = ret + ['-vcpus', str(self.vm.getVCpuCount())]
488 if self.kernel:
489 log.debug("kernel = %s", self.kernel)
490 ret = ret + ['-kernel', self.kernel]
491 if self.ramdisk:
492 log.debug("ramdisk = %s", self.ramdisk)
493 ret = ret + ['-initrd', self.ramdisk]
494 if self.cmdline:
495 log.debug("cmdline = %s", self.cmdline)
496 ret = ret + ['-append', self.cmdline]
499 dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
500 'localtime', 'serial', 'stdvga', 'isa',
501 'acpi', 'usb', 'usbdevice' ]
503 for a in dmargs:
504 v = vmConfig['platform'].get(a)
506 # python doesn't allow '-' in variable names
507 if a == 'stdvga': a = 'std-vga'
508 if a == 'keymap': a = 'k'
510 # Handle booleans gracefully
511 if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']:
512 try:
513 if v != None: v = int(v)
514 if v: ret.append("-%s" % a)
515 except (ValueError, TypeError):
516 pass # if we can't convert it to a sane type, ignore it
517 else:
518 if v:
519 ret.append("-%s" % a)
520 ret.append("%s" % v)
522 if a in ['fda', 'fdb']:
523 if v:
524 if not os.path.isabs(v):
525 raise VmError("Floppy file %s does not exist." % v)
526 log.debug("args: %s, val: %s" % (a,v))
528 # Handle disk/network related options
529 mac = None
530 nics = 0
532 for devuuid in vmConfig['vbd_refs']:
533 devinfo = vmConfig['devices'][devuuid][1]
534 uname = devinfo.get('uname')
535 if uname is not None and 'file:' in uname:
536 (_, vbdparam) = string.split(uname, ':', 1)
537 if not os.path.isfile(vbdparam):
538 raise VmError('Disk image does not exist: %s' %
539 vbdparam)
541 for devuuid in vmConfig['vif_refs']:
542 devinfo = vmConfig['devices'][devuuid][1]
543 dtype = devinfo.get('type', 'ioemu')
544 if dtype != 'ioemu':
545 continue
546 nics += 1
547 mac = devinfo.get('mac')
548 if mac is None:
549 raise VmError("MAC address not specified or generated.")
550 bridge = devinfo.get('bridge', 'xenbr0')
551 model = devinfo.get('model', 'rtl8139')
552 ret.append("-net")
553 ret.append("nic,vlan=%d,macaddr=%s,model=%s" %
554 (nics, mac, model))
555 ret.append("-net")
556 ret.append("tap,vlan=%d,bridge=%s" % (nics, bridge))
558 return ret
560 def getDeviceModelArgs(self, restore = False):
561 args = ImageHandler.getDeviceModelArgs(self, restore)
562 args = args + ([ "-M", "xenfv"])
563 if restore:
564 args = args + ([ "-loadvm", "/var/lib/xen/qemu-save.%d" %
565 self.vm.getDomid() ])
566 return args
568 def buildDomain(self):
569 store_evtchn = self.vm.getStorePort()
571 mem_mb = self.getRequiredInitialReservation() / 1024
573 log.debug("domid = %d", self.vm.getDomid())
574 log.debug("image = %s", self.loader)
575 log.debug("store_evtchn = %d", store_evtchn)
576 log.debug("memsize = %d", mem_mb)
577 log.debug("vcpus = %d", self.vm.getVCpuCount())
578 log.debug("acpi = %d", self.acpi)
579 log.debug("apic = %d", self.apic)
581 rc = xc.hvm_build(domid = self.vm.getDomid(),
582 image = self.loader,
583 memsize = mem_mb,
584 vcpus = self.vm.getVCpuCount(),
585 acpi = self.acpi,
586 apic = self.apic)
587 rc['notes'] = { 'SUSPEND_CANCEL': 1 }
589 rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
590 HVM_PARAM_STORE_PFN)
591 xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN,
592 store_evtchn)
594 return rc
597 class IA64_HVM_ImageHandler(HVMImageHandler):
599 def configure(self, vmConfig):
600 HVMImageHandler.configure(self, vmConfig)
601 self.vhpt = int(vmConfig['platform'].get('vhpt', 0))
603 def buildDomain(self):
604 xc.nvram_init(self.vm.getName(), self.vm.getDomid())
605 xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_VHPT_SIZE, self.vhpt)
606 if self.guest_os_type is not None:
607 xc.set_os_type(self.guest_os_type.lower(), self.vm.getDomid())
608 return HVMImageHandler.buildDomain(self)
610 def getRequiredAvailableMemory(self, mem_kb):
611 page_kb = 16
612 # ROM size for guest firmware, io page, xenstore page
613 # buffer io page, buffer pio page and memmap info page
614 extra_pages = 1024 + 5
615 return mem_kb + extra_pages * page_kb
617 def getRequiredInitialReservation(self):
618 return self.vm.getMemoryTarget()
620 def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
621 # Explicit shadow memory is not a concept
622 return 0
624 def getDeviceModelArgs(self, restore = False):
625 args = HVMImageHandler.getDeviceModelArgs(self, restore)
626 args = args + ([ "-m", "%s" %
627 (self.getRequiredInitialReservation() / 1024) ])
628 return args
631 class IA64_Linux_ImageHandler(LinuxImageHandler):
633 def configure(self, vmConfig):
634 LinuxImageHandler.configure(self, vmConfig)
635 self.vhpt = int(vmConfig['platform'].get('vhpt', 0))
638 class X86_HVM_ImageHandler(HVMImageHandler):
640 def configure(self, vmConfig):
641 HVMImageHandler.configure(self, vmConfig)
642 self.pae = int(vmConfig['platform'].get('pae', 0))
644 def buildDomain(self):
645 xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_PAE_ENABLED, self.pae)
646 return HVMImageHandler.buildDomain(self)
648 def getRequiredAvailableMemory(self, mem_kb):
649 # Add 8 MiB overhead for QEMU's video RAM.
650 return mem_kb + 8192
652 def getRequiredInitialReservation(self):
653 return self.vm.getMemoryTarget()
655 def getRequiredMaximumReservation(self):
656 return self.vm.getMemoryMaximum()
658 def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
659 # 256 pages (1MB) per vcpu,
660 # plus 1 page per MiB of RAM for the P2M map,
661 # plus 1 page per MiB of RAM to shadow the resident processes.
662 # This is higher than the minimum that Xen would allocate if no value
663 # were given (but the Xen minimum is for safety, not performance).
664 return max(4 * (256 * self.vm.getVCpuCount() + 2 * (maxmem_kb / 1024)),
665 shadow_mem_kb)
668 class X86_Linux_ImageHandler(LinuxImageHandler):
670 def buildDomain(self):
671 # set physical mapping limit
672 # add an 8MB slack to balance backend allocations.
673 mem_kb = self.getRequiredMaximumReservation() + (8 * 1024)
674 xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb)
675 return LinuxImageHandler.buildDomain(self)
677 _handlers = {
678 "powerpc": {
679 "linux": PPC_LinuxImageHandler,
680 },
681 "ia64": {
682 "linux": IA64_Linux_ImageHandler,
683 "hvm": IA64_HVM_ImageHandler,
684 },
685 "x86": {
686 "linux": X86_Linux_ImageHandler,
687 "hvm": X86_HVM_ImageHandler,
688 },
689 }
691 def findImageHandlerClass(image):
692 """Find the image handler class for an image config.
694 @param image config
695 @return ImageHandler subclass or None
696 """
697 image_type = image.image_type()
698 try:
699 return _handlers[arch.type][image_type]
700 except KeyError:
701 raise VmError('unknown image type: ' + image_type)