ia64/xen-unstable

annotate tools/python/xen/xend/image.py @ 19488:79f734040a83

xend: modify a warning log message

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Apr 01 11:47:59 2009 +0100 (2009-04-01)
parents 5d701be7c37b
children b920a2f799d9
rev   line source
kaf24@6079 1 #============================================================================
kaf24@6079 2 # This library is free software; you can redistribute it and/or
kaf24@6079 3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
kaf24@6079 4 # License as published by the Free Software Foundation.
kaf24@6079 5 #
kaf24@6079 6 # This library is distributed in the hope that it will be useful,
kaf24@6079 7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
kaf24@6079 8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
kaf24@6079 9 # Lesser General Public License for more details.
kaf24@6079 10 #
kaf24@6079 11 # You should have received a copy of the GNU Lesser General Public
kaf24@6079 12 # License along with this library; if not, write to the Free Software
kaf24@6079 13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kaf24@6079 14 #============================================================================
kaf24@6079 15 # Copyright (C) 2005 Mike Wray <mike.wray@hp.com>
ewan@14361 16 # Copyright (C) 2005-2007 XenSource Ltd
kaf24@6079 17 #============================================================================
kaf24@6079 18
emellor@7006 19
keir@16272 20 import os, os.path, string
adsharma@6201 21 import re
kaf24@10109 22 import math
Tim@15646 23 import time
kfraser@12192 24 import signal
keir@17849 25 import thread
keir@17849 26 import fcntl
keir@17849 27 import sys
keir@17849 28 import errno
keir@17849 29 import glob
keir@17849 30 import traceback
keir@19335 31 import platform
cl349@5343 32
emellor@6940 33 import xen.lowlevel.xc
keir@16137 34 from xen.xend.XendConstants import *
ewan@14362 35 from xen.xend.XendError import VmError, XendError, HVMRequired
cl349@5343 36 from xen.xend.XendLogging import log
atse@13771 37 from xen.xend.XendOptions import instance as xenopts
Tim@15646 38 from xen.xend.xenstore.xstransact import xstransact
ke@8648 39 from xen.xend.xenstore.xswatch import xswatch
ewan@11340 40 from xen.xend import arch
keir@16271 41 from xen.xend import XendOptions
keir@17849 42 from xen.util import oshelp
keir@17849 43 from xen.util import utils
keir@19333 44 from xen.xend import osdep
cl349@5343 45
emellor@7973 46 xc = xen.lowlevel.xc.xc()
emellor@6940 47
cl349@6898 48 MAX_GUEST_CMDLINE = 1024
cl349@6898 49
keir@17849 50 sentinel_path_prefix = '/var/run/xend/dm-'
keir@17849 51 sentinel_fifos_inuse = { }
keir@17849 52
keir@17849 53 def cleanup_stale_sentinel_fifos():
keir@17849 54 for path in glob.glob(sentinel_path_prefix + '*.fifo'):
keir@17849 55 if path in sentinel_fifos_inuse: continue
keir@17849 56 try: os.unlink(path)
keir@17849 57 except OSError, e:
keir@17849 58 log.warning('could not delete stale fifo %s: %s',
keir@17849 59 path, utils.exception_string(e))
emellor@7056 60
ewan@14361 61 def create(vm, vmConfig):
emellor@7056 62 """Create an image handler for a vm.
emellor@7056 63
emellor@7056 64 @return ImageHandler instance
emellor@7056 65 """
ewan@14361 66 return findImageHandlerClass(vmConfig)(vm, vmConfig)
emellor@7056 67
emellor@7056 68
cl349@5343 69 class ImageHandler:
cl349@5343 70 """Abstract base class for image handlers.
cl349@5343 71
cl349@5343 72 createImage() is called to configure and build the domain from its
cl349@5343 73 kernel image and ramdisk etc.
cl349@5343 74
cl349@5343 75 The method buildDomain() is used to build the domain, and must be
cl349@5343 76 defined in a subclass. Usually this is the only method that needs
cl349@5343 77 defining in a subclass.
cl349@5343 78
cl349@5343 79 The method createDeviceModel() is called to create the domain device
keir@16236 80 model.
cl349@5343 81
keir@16236 82 The method destroyDeviceModel() is called to reap the device model
cl349@5343 83 """
cl349@5343 84
cl349@5343 85 ostype = None
cl349@5343 86
cl349@5343 87
ewan@14361 88 def __init__(self, vm, vmConfig):
cl349@6898 89 self.vm = vm
emellor@7056 90
ewan@13208 91 self.bootloader = False
emellor@7056 92 self.kernel = None
emellor@7056 93 self.ramdisk = None
emellor@7056 94 self.cmdline = None
emellor@7056 95
ewan@14361 96 self.configure(vmConfig)
emellor@7047 97
ewan@14361 98 def configure(self, vmConfig):
atse@12686 99 """Config actions common to all unix-like domains."""
ewan@13208 100 if '_temp_using_bootloader' in vmConfig:
ewan@13208 101 self.bootloader = True
ewan@13208 102 self.kernel = vmConfig['_temp_kernel']
ewan@13208 103 self.cmdline = vmConfig['_temp_args']
ewan@13208 104 self.ramdisk = vmConfig['_temp_ramdisk']
ewan@13208 105 else:
ewan@13208 106 self.kernel = vmConfig['PV_kernel']
ewan@13208 107 self.cmdline = vmConfig['PV_args']
ewan@13208 108 self.ramdisk = vmConfig['PV_ramdisk']
cl349@6898 109 self.vm.storeVm(("image/ostype", self.ostype),
cl349@6898 110 ("image/kernel", self.kernel),
cl349@6898 111 ("image/cmdline", self.cmdline),
cl349@6898 112 ("image/ramdisk", self.ramdisk))
keir@17233 113 self.vm.permissionsVm("image/cmdline", { 'dom': self.vm.getDomid(), 'read': True } )
cl349@5343 114
keir@16236 115 self.device_model = vmConfig['platform'].get('device_model')
keir@16236 116
keir@16236 117 self.display = vmConfig['platform'].get('display')
keir@16236 118 self.xauthority = vmConfig['platform'].get('xauthority')
keir@18266 119 self.vncconsole = int(vmConfig['platform'].get('vncconsole', 0))
keir@17023 120 self.dmargs = self.parseDeviceModelArgs(vmConfig)
keir@16236 121 self.pid = None
keir@19487 122 rtc_timeoffset = int(vmConfig['platform'].get('rtc_timeoffset', 0))
keir@19487 123 if vmConfig['platform'].get('localtime', 0):
keir@19487 124 if time.localtime(time.time())[8]:
keir@19487 125 rtc_timeoffset -= time.altzone
keir@19487 126 else:
keir@19487 127 rtc_timeoffset -= time.timezone
keir@19487 128 if rtc_timeoffset != 0:
keir@19487 129 xc.domain_set_time_offset(self.vm.getDomid(), rtc_timeoffset)
keir@16236 130
keir@17832 131 self.cpuid = None
keir@17832 132 self.cpuid_check = None
keir@17832 133 if 'cpuid' in vmConfig:
keir@17832 134 self.cpuid = vmConfig['cpuid'];
keir@17832 135 if 'cpuid_check' in vmConfig:
keir@17832 136 self.cpuid_check = vmConfig['cpuid_check']
emellor@7024 137
emellor@7799 138 def cleanupBootloading(self):
ewan@13042 139 if self.bootloader:
ewan@13042 140 self.unlink(self.kernel)
ewan@13042 141 self.unlink(self.ramdisk)
emellor@7024 142
emellor@7024 143
cl349@5343 144 def unlink(self, f):
cl349@5343 145 if not f: return
cl349@5343 146 try:
cl349@5343 147 os.unlink(f)
cl349@5343 148 except OSError, ex:
cl349@5343 149 log.warning("error removing bootloader file '%s': %s", f, ex)
cl349@5343 150
cl349@5343 151
cl349@5343 152 def createImage(self):
cl349@5343 153 """Entry point to create domain memory image.
cl349@5343 154 Override in subclass if needed.
cl349@5343 155 """
emellor@7433 156 return self.createDomain()
emellor@7433 157
cl349@5343 158
cl349@5343 159 def createDomain(self):
cl349@5343 160 """Build the domain boot image.
cl349@5343 161 """
cl349@5343 162 # Set params and call buildDomain().
cl349@5343 163
keir@16963 164 if self.kernel and not os.path.isfile(self.kernel):
cl349@5343 165 raise VmError('Kernel image does not exist: %s' % self.kernel)
cl349@5343 166 if self.ramdisk and not os.path.isfile(self.ramdisk):
cl349@5343 167 raise VmError('Kernel ramdisk does not exist: %s' % self.ramdisk)
cl349@6898 168 if len(self.cmdline) >= MAX_GUEST_CMDLINE:
emellor@6940 169 log.warning('kernel cmdline too long, domain %d',
emellor@7025 170 self.vm.getDomid())
cl349@5343 171
cl349@5343 172 log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype,
emellor@7025 173 self.vm.getDomid(), self.vm.getVCpuCount())
emellor@7433 174
emellor@7433 175 result = self.buildDomain()
emellor@7433 176
emellor@7433 177 if isinstance(result, dict):
emellor@7433 178 return result
emellor@7433 179 else:
emellor@7433 180 raise VmError('Building domain failed: ostype=%s dom=%d err=%s'
emellor@7433 181 % (self.ostype, self.vm.getDomid(), str(result)))
emellor@7433 182
ewan@11425 183 def getRequiredAvailableMemory(self, mem_kb):
ewan@11425 184 """@param mem_kb The configured maxmem or memory, in KiB.
ewan@11425 185 @return The corresponding required amount of memory for the domain,
ewan@11425 186 also in KiB. This is normally the given mem_kb, but architecture- or
ewan@11425 187 image-specific code may override this to add headroom where
ewan@11425 188 necessary."""
kaf24@10109 189 return mem_kb
cl349@5343 190
kfraser@12218 191 def getRequiredInitialReservation(self):
ewan@11425 192 """@param mem_kb The configured memory, in KiB.
ewan@11425 193 @return The corresponding required amount of memory to be free, also
ewan@11425 194 in KiB. This is normally the same as getRequiredAvailableMemory, but
ewan@11425 195 architecture- or image-specific code may override this to
ewan@11425 196 add headroom where necessary."""
kfraser@12218 197 return self.getRequiredAvailableMemory(self.vm.getMemoryTarget())
ewan@11425 198
kfraser@12994 199 def getRequiredMaximumReservation(self):
kfraser@12994 200 """@param mem_kb The maximum possible memory, in KiB.
kfraser@12994 201 @return The corresponding required amount of memory to be free, also
kfraser@12994 202 in KiB. This is normally the same as getRequiredAvailableMemory, but
kfraser@12994 203 architecture- or image-specific code may override this to
kfraser@12994 204 add headroom where necessary."""
kfraser@12994 205 return self.getRequiredAvailableMemory(self.vm.getMemoryMaximum())
kfraser@12994 206
ewan@11425 207 def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
ewan@11425 208 """@param shadow_mem_kb The configured shadow memory, in KiB.
ewan@11425 209 @param maxmem_kb The configured maxmem, in KiB.
ewan@11425 210 @return The corresponding required amount of shadow memory, also in
ewan@11425 211 KiB."""
tdeegan@11172 212 # PV domains don't need any shadow memory
tdeegan@11172 213 return 0
tdeegan@11172 214
cl349@5343 215 def buildDomain(self):
cl349@5343 216 """Build the domain. Define in subclass."""
cl349@5343 217 raise NotImplementedError()
cl349@5343 218
keir@17517 219 def prepareEnvironment(self):
keir@17517 220 """Prepare the environment for the execution of the domain. This
keir@17517 221 method is called before any devices are set up."""
keir@17517 222
keir@17517 223 domid = self.vm.getDomid()
keir@17944 224
keir@17517 225 # Delete left-over pipes
keir@17517 226 try:
keir@17517 227 os.unlink('/var/run/tap/qemu-read-%d' % domid)
keir@17517 228 os.unlink('/var/run/tap/qemu-write-%d' % domid)
keir@17517 229 except:
keir@17517 230 pass
keir@17517 231
keir@17517 232 # No device model, don't create pipes
keir@17517 233 if self.device_model is None:
keir@17517 234 return
keir@17517 235
keir@19335 236 if platform.system() != 'SunOS':
keir@19335 237 # If we use a device model, the pipes for communication between
keir@19335 238 # blktapctrl and ioemu must be present before the devices are
keir@19335 239 # created (blktapctrl must access them for new block devices)
keir@19350 240
keir@19350 241 try:
keir@19350 242 os.makedirs('/var/run/tap', 0755)
keir@19350 243 except:
keir@19350 244 pass
keir@17517 245
keir@19335 246 try:
keir@19335 247 os.mkfifo('/var/run/tap/qemu-read-%d' % domid, 0600)
keir@19335 248 os.mkfifo('/var/run/tap/qemu-write-%d' % domid, 0600)
keir@19335 249 except OSError, e:
keir@19335 250 log.warn('Could not create blktap pipes for domain %d' % domid)
keir@19335 251 log.exception(e)
keir@19335 252 pass
keir@17517 253
keir@17517 254
arun@5608 255 # Return a list of cmd line args to the device models based on the
arun@5608 256 # xm config file
ewan@13609 257 def parseDeviceModelArgs(self, vmConfig):
keir@16236 258 ret = ["-domain-name", str(self.vm.info['name_label'])]
arun@5608 259
keir@18622 260 xen_extended_power_mgmt = int(vmConfig['platform'].get(
keir@18622 261 'xen_extended_power_mgmt', 0))
keir@18622 262 if xen_extended_power_mgmt != 0:
keir@18622 263 xstransact.Store("/local/domain/0/device-model/%i"
keir@18622 264 % self.vm.getDomid(),
keir@18622 265 ('xen_extended_power_mgmt',
keir@18622 266 xen_extended_power_mgmt))
keir@18622 267
atse@13771 268 # Find RFB console device, and if it exists, make QEMU enable
atse@13771 269 # the VNC console.
Tim@14389 270 if int(vmConfig['platform'].get('nographic', 0)) != 0:
atse@13771 271 # skip vnc init if nographic is set
cl349@6898 272 ret.append('-nographic')
cl349@6898 273 return ret
ewan@12191 274
keir@19037 275 vram = str(vmConfig['platform'].get('videoram',4))
keir@19037 276 ret.append('-videoram')
keir@19037 277 ret.append(vram)
keir@19037 278
atse@13771 279 vnc_config = {}
ewan@14361 280 has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
ewan@14361 281 has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
keir@17253 282 opengl = 1
keir@18119 283 keymap = vmConfig['platform'].get("keymap")
atse@13771 284 for dev_uuid in vmConfig['console_refs']:
atse@13789 285 dev_type, dev_info = vmConfig['devices'][dev_uuid]
atse@13789 286 if dev_type == 'vfb':
keir@18119 287 if 'keymap' in dev_info:
keir@18119 288 keymap = dev_info.get('keymap',{})
keir@19287 289 if int(dev_info.get('vnc', 0)) != 0 :
keir@19287 290 has_vnc = True
keir@19287 291 if int(dev_info.get('sdl', 0)) != 0 :
keir@19287 292 has_sdl = True
keir@19287 293 if has_sdl:
keir@17023 294 self.display = dev_info.get('display', {})
keir@17023 295 self.xauthority = dev_info.get('xauthority', {})
keir@17253 296 opengl = int(dev_info.get('opengl', opengl))
keir@19287 297 if has_vnc:
keir@17023 298 vnc_config = dev_info.get('other_config', {})
atse@13771 299 break
atse@12686 300
keir@16236 301 if keymap:
keir@16236 302 ret.append("-k")
keir@16236 303 ret.append(keymap)
keir@16236 304
ewan@13814 305 if has_vnc:
ewan@13814 306 if not vnc_config:
ewan@13814 307 for key in ('vncunused', 'vnclisten', 'vncdisplay',
ewan@13814 308 'vncpasswd'):
ewan@14361 309 if key in vmConfig['platform']:
ewan@14361 310 vnc_config[key] = vmConfig['platform'][key]
keir@16271 311 if vnc_config.has_key("vncpasswd"):
keir@16271 312 passwd = vnc_config["vncpasswd"]
keir@16271 313 else:
keir@16271 314 passwd = XendOptions.instance().get_vncpasswd_default()
keir@16271 315 vncopts = ""
keir@16271 316 if passwd:
keir@16271 317 self.vm.storeVm("vncpasswd", passwd)
keir@16857 318 self.vm.permissionsVm("vncpasswd", { 'dom': self.vm.getDomid(), 'read': True } )
keir@16271 319 vncopts = vncopts + ",password"
keir@16271 320 log.debug("Stored a VNC password for vfb access")
keir@16271 321 else:
keir@16271 322 log.debug("No VNC passwd configured for vfb access")
ewan@12191 323
keir@16272 324 if XendOptions.instance().get_vnc_tls():
keir@16272 325 vncx509certdir = XendOptions.instance().get_vnc_x509_cert_dir()
keir@16272 326 vncx509verify = XendOptions.instance().get_vnc_x509_verify()
keir@16272 327
keir@16272 328 if not os.path.exists(vncx509certdir):
keir@16272 329 raise VmError("VNC x509 certificate dir %s does not exist" % vncx509certdir)
keir@16272 330
keir@16272 331 if vncx509verify:
keir@16272 332 vncopts = vncopts + ",tls,x509verify=%s" % vncx509certdir
keir@16272 333 else:
keir@16272 334 vncopts = vncopts + ",tls,x509=%s" % vncx509certdir
keir@16272 335
keir@16272 336
ewan@13814 337 vnclisten = vnc_config.get('vnclisten',
keir@16271 338 XendOptions.instance().get_vnclisten_address())
keir@17611 339 vncdisplay = int(vnc_config.get('vncdisplay', 0))
Christian@15067 340 ret.append('-vnc')
keir@16271 341 ret.append("%s:%s%s" % (vnclisten, vncdisplay, vncopts))
keir@16271 342
keir@17611 343 if int(vnc_config.get('vncunused', 1)) != 0:
Christian@15067 344 ret.append('-vncunused')
ewan@13814 345
keir@19287 346 if has_sdl:
keir@19287 347 ret.append('-sdl')
keir@17253 348 if int(vmConfig['platform'].get('opengl', opengl)) != 1 :
keir@17242 349 ret.append('-disable-opengl')
keir@19287 350
keir@19287 351 if not has_sdl and not has_vnc :
ewan@13814 352 ret.append('-nographic')
ewan@12191 353
kfraser@14826 354 if int(vmConfig['platform'].get('monitor', 0)) != 0:
kfraser@15039 355 ret = ret + ['-monitor', 'vc']
cl349@6898 356 return ret
cl349@6898 357
keir@16236 358 def getDeviceModelArgs(self, restore = False):
keir@16236 359 args = [self.device_model]
keir@16236 360 args = args + ([ "-d", "%d" % self.vm.getDomid() ])
keir@16236 361 args = args + self.dmargs
keir@16236 362 return args
keir@16236 363
keir@17849 364 def _openSentinel(self, sentinel_path_fifo):
keir@17849 365 self.sentinel_fifo = file(sentinel_path_fifo, 'r')
keir@17849 366 self.sentinel_lock = thread.allocate_lock()
keir@17849 367 oshelp.fcntl_setfd_cloexec(self.sentinel_fifo, True)
keir@17849 368 sentinel_fifos_inuse[sentinel_path_fifo] = 1
keir@17849 369 self.sentinel_path_fifo = sentinel_path_fifo
keir@17849 370
Tim@13491 371 def createDeviceModel(self, restore = False):
keir@16236 372 if self.device_model is None:
keir@16236 373 return
cl349@6898 374 if self.pid:
cl349@6898 375 return
cl349@5343 376 # Execute device model.
cl349@5343 377 #todo: Error handling
keir@16236 378 args = self.getDeviceModelArgs(restore)
arun@5608 379 env = dict(os.environ)
jrb44@7456 380 if self.display:
jrb44@7456 381 env['DISPLAY'] = self.display
kaf24@8453 382 if self.xauthority:
kaf24@8453 383 env['XAUTHORITY'] = self.xauthority
keir@17849 384 unique_id = "%i-%i" % (self.vm.getDomid(), time.time())
keir@17849 385 sentinel_path = sentinel_path_prefix + unique_id
keir@17849 386 sentinel_path_fifo = sentinel_path + '.fifo'
keir@17849 387 os.mkfifo(sentinel_path_fifo, 0600)
keir@17849 388 sentinel_write = file(sentinel_path_fifo, 'r+')
keir@17849 389 self._openSentinel(sentinel_path_fifo)
keir@17849 390 self.vm.storeDom("image/device-model-fifo", sentinel_path_fifo)
keir@16857 391 xstransact.Mkdir("/local/domain/0/device-model/%i" % self.vm.getDomid())
keir@16857 392 xstransact.SetPermissions("/local/domain/0/device-model/%i" % self.vm.getDomid(),
keir@16857 393 { 'dom': self.vm.getDomid(), 'read': True, 'write': True })
cl349@6898 394 log.info("spawning device models: %s %s", self.device_model, args)
atse@12686 395 # keep track of pid and spawned options to kill it later
keir@17143 396
keir@17849 397 self.logfile = "/var/log/xen/qemu-dm-%s.log" % str(self.vm.info['name_label'])
keir@17932 398
keir@17932 399 # rotate log
keir@17933 400 logfile_mode = os.O_WRONLY|os.O_CREAT|os.O_APPEND
keir@17932 401 logrotate_count = XendOptions.instance().get_qemu_dm_logrotate_count()
keir@17932 402 if logrotate_count > 0:
keir@17933 403 logfile_mode |= os.O_TRUNC
keir@17932 404 if os.path.exists("%s.%d" % (self.logfile, logrotate_count)):
keir@17932 405 os.unlink("%s.%d" % (self.logfile, logrotate_count))
keir@17932 406 for n in range(logrotate_count - 1, 0, -1):
keir@17932 407 if os.path.exists("%s.%d" % (self.logfile, n)):
keir@17932 408 os.rename("%s.%d" % (self.logfile, n),
keir@17932 409 "%s.%d" % (self.logfile, (n + 1)))
keir@17932 410 if os.path.exists(self.logfile):
keir@17932 411 os.rename(self.logfile, self.logfile + ".1")
keir@17143 412
keir@17143 413 null = os.open("/dev/null", os.O_RDONLY)
keir@17933 414 logfd = os.open(self.logfile, logfile_mode)
keir@17143 415
keir@17849 416 sys.stderr.flush()
keir@19333 417 contract = osdep.prefork("%s:%d" %
keir@19333 418 (self.vm.getName(), self.vm.getDomid()))
keir@17143 419 pid = os.fork()
keir@17143 420 if pid == 0: #child
keir@17143 421 try:
keir@19333 422 osdep.postfork(contract)
keir@17143 423 os.dup2(null, 0)
keir@17143 424 os.dup2(logfd, 1)
keir@17143 425 os.dup2(logfd, 2)
keir@17143 426 os.close(null)
keir@17143 427 os.close(logfd)
keir@17849 428 self.sentinel_fifo.close()
keir@17143 429 try:
keir@17143 430 os.execve(self.device_model, args, env)
keir@17849 431 except Exception, e:
keir@17849 432 print >>sys.stderr, (
keir@17849 433 'failed to set up fds or execute dm %s: %s' %
keir@17849 434 (self.device_model, utils.exception_string(e)))
keir@17849 435 os._exit(126)
keir@17143 436 except:
keir@17143 437 os._exit(127)
keir@17143 438 else:
keir@19333 439 osdep.postfork(contract, abandon=True)
keir@17143 440 self.pid = pid
keir@17143 441 os.close(null)
keir@17143 442 os.close(logfd)
keir@17849 443 sentinel_write.close()
keir@18572 444 self.vm.storeDom("image/device-model-pid", self.pid)
arun@5608 445 log.info("device model pid: %d", self.pid)
keir@17849 446 # we would very much prefer not to have a thread here and instead
keir@17849 447 # have a callback but sadly we don't have Twisted in xend
keir@17849 448 self.sentinel_thread = thread.start_new_thread(self._sentinel_watch,())
cl349@5343 449
keir@17082 450 def signalDeviceModel(self, cmd, ret, par = None):
keir@16236 451 if self.device_model is None:
keir@16236 452 return
keir@17082 453 # Signal the device model to for action
keir@17082 454 if cmd is '' or ret is '':
keir@17082 455 raise VmError('need valid command and result when signal device model')
keir@17082 456
keir@17082 457 orig_state = xstransact.Read("/local/domain/0/device-model/%i/state"
keir@17082 458 % self.vm.getDomid())
keir@17082 459
keir@17082 460 if par is not None:
keir@17082 461 xstransact.Store("/local/domain/0/device-model/%i"
keir@17082 462 % self.vm.getDomid(), ('parameter', par))
keir@17082 463
Tim@15646 464 xstransact.Store("/local/domain/0/device-model/%i"
keir@17082 465 % self.vm.getDomid(), ('command', cmd))
Tim@15646 466 # Wait for confirmation. Could do this with a watch but we'd
Tim@15646 467 # still end up spinning here waiting for the watch to fire.
Tim@15646 468 state = ''
Tim@15646 469 count = 0
keir@17082 470 while state != ret:
Tim@15646 471 state = xstransact.Read("/local/domain/0/device-model/%i/state"
Tim@15646 472 % self.vm.getDomid())
Tim@15646 473 time.sleep(0.1)
Tim@15646 474 count += 1
Tim@15646 475 if count > 100:
keir@17082 476 raise VmError('Timed out waiting for device model action')
keir@17082 477
keir@17082 478 #resotre orig state
keir@17082 479 xstransact.Store("/local/domain/0/device-model/%i"
keir@17082 480 % self.vm.getDomid(), ('state', orig_state))
keir@17082 481 log.info("signalDeviceModel:restore dm state to %s", orig_state)
keir@17082 482
keir@17082 483 def saveDeviceModel(self):
keir@17082 484 # Signal the device model to pause itself and save its state
keir@17082 485 self.signalDeviceModel('save', 'paused')
Tim@15646 486
Tim@15646 487 def resumeDeviceModel(self):
keir@16236 488 if self.device_model is None:
keir@16236 489 return
Tim@15646 490 # Signal the device model to resume activity after pausing to save.
Tim@15646 491 xstransact.Store("/local/domain/0/device-model/%i"
Tim@15646 492 % self.vm.getDomid(), ('command', 'continue'))
Tim@15646 493
keir@17849 494 def _dmfailed(self, message):
keir@17849 495 log.warning("domain %s: %s", self.vm.getName(), message)
keir@19471 496 try:
keir@19471 497 xc.domain_shutdown(self.vm.getDomid(), DOMAIN_CRASH)
keir@19471 498 except:
keir@19471 499 pass
keir@17849 500
ewan@12710 501 def recreate(self):
keir@16236 502 if self.device_model is None:
keir@16236 503 return
keir@17849 504 name = self.vm.getName()
keir@17849 505 sentinel_path_fifo = self.vm.readDom('image/device-model-fifo')
keir@17849 506 fifo_fd = -1
keir@17849 507 log.debug("rediscovering %s", sentinel_path_fifo)
keir@17849 508 if sentinel_path_fifo is None:
keir@17849 509 log.debug("%s device model no sentinel, cannot rediscover", name)
keir@17849 510 else:
keir@17849 511 try:
keir@17849 512 # We open it O_WRONLY because that fails ENXIO if no-one
keir@17849 513 # has it open for reading (see SuSv3). The dm process got
keir@17849 514 # a read/write descriptor from our earlier invocation.
keir@17849 515 fifo_fd = os.open(sentinel_path_fifo, os.O_WRONLY|os.O_NONBLOCK)
keir@17849 516 except OSError, e:
keir@17849 517 if e.errno == errno.ENXIO:
keir@17849 518 self._dmfailed("%s device model no longer running"%name)
keir@17849 519 elif e.errno == errno.ENOENT:
keir@17849 520 log.debug("%s device model sentinel %s absent!",
keir@17849 521 name, sentinel_path_fifo)
keir@17849 522 else:
keir@17849 523 raise
keir@17849 524 if fifo_fd >= 0:
keir@17849 525 self._openSentinel(sentinel_path_fifo)
keir@17849 526 os.close(fifo_fd)
keir@18597 527 self.pid = self.vm.gatherDom(('image/device-model-pid', int))
keir@17849 528 log.debug("%s device model rediscovered, pid %s sentinel fifo %s",
keir@17849 529 name, self.pid, sentinel_path_fifo)
keir@17849 530 self.sentinel_thread = thread.start_new_thread(self._sentinel_watch,())
keir@17849 531
keir@17849 532 def _sentinel_watch(self):
keir@17849 533 log.info("waiting for sentinel_fifo")
keir@17849 534 try: self.sentinel_fifo.read(1)
keir@17849 535 except OSError, e: pass
keir@17849 536 self.sentinel_lock.acquire()
keir@19488 537 if self.pid:
keir@19488 538 try:
keir@17849 539 (p,st) = os.waitpid(self.pid, os.WNOHANG)
keir@17849 540 if p == self.pid:
keir@17849 541 message = oshelp.waitstatus_description(st)
keir@17849 542 else:
keir@17849 543 # obviously it is malfunctioning, kill it now
keir@17849 544 try:
keir@17849 545 os.kill(self.pid, signal.SIGKILL)
keir@17849 546 message = "malfunctioning (closed sentinel), killed"
keir@17849 547 except:
keir@17849 548 message = "malfunctioning or died ?"
keir@17849 549 message = "pid %d: %s" % (self.pid, message)
keir@19488 550 except Exception, e:
keir@19488 551 message = "waitpid failed: %s" % utils.exception_string(e)
keir@19488 552 message = "device model failure: %s" % message
keir@19488 553 try: message += "; see %s " % self.logfile
keir@19488 554 except: pass
keir@19488 555 self._dmfailed(message)
keir@19488 556 self.pid = None
keir@19488 557 else:
keir@19488 558 log.info("%s device model terminated", self.vm.getName())
keir@17849 559 self.sentinel_lock.release()
ewan@12710 560
keir@16236 561 def destroyDeviceModel(self):
keir@16236 562 if self.device_model is None:
keir@16236 563 return
keir@16236 564 if self.pid:
keir@17849 565 self.sentinel_lock.acquire()
ewan@12710 566 try:
keir@17849 567 try:
keir@17849 568 os.kill(self.pid, signal.SIGHUP)
keir@17849 569 except OSError, exn:
keir@17849 570 log.exception(exn)
keir@19157 571 # Try to reap the child every 100ms for 10s. Then SIGKILL it.
keir@19157 572 for i in xrange(100):
keir@19157 573 try:
keir@17849 574 (p, rv) = os.waitpid(self.pid, os.WNOHANG)
keir@17849 575 if p == self.pid:
keir@17849 576 break
keir@19157 577 except OSError:
keir@19157 578 # This is expected if Xend has been restarted within
keir@19157 579 # the life of this domain. In this case, we can kill
keir@19157 580 # the process, but we can't wait for it because it's
keir@19157 581 # not our child. We continue this loop, and after it is
keir@19157 582 # terminated make really sure the process is going away
keir@19157 583 # (SIGKILL).
keir@19157 584 pass
keir@19157 585 time.sleep(0.1)
keir@19157 586 else:
keir@19157 587 log.warning("DeviceModel %d took more than 10s "
keir@19157 588 "to terminate: sending SIGKILL" % self.pid)
keir@19157 589 try:
keir@17849 590 os.kill(self.pid, signal.SIGKILL)
keir@17849 591 os.waitpid(self.pid, 0)
keir@19157 592 except OSError:
keir@19157 593 # This happens if the process doesn't exist.
keir@19157 594 pass
keir@17849 595 state = xstransact.Remove("/local/domain/0/device-model/%i"
keir@17849 596 % self.vm.getDomid())
keir@17849 597 finally:
keir@17849 598 self.pid = None
keir@17849 599 self.sentinel_lock.release()
keir@17517 600
keir@17517 601 try:
keir@17517 602 os.unlink('/var/run/tap/qemu-read-%d' % self.vm.getDomid())
keir@17517 603 os.unlink('/var/run/tap/qemu-write-%d' % self.vm.getDomid())
keir@17517 604 except:
keir@17517 605 pass
keir@17849 606 try:
keir@17849 607 del sentinel_fifos_inuse[self.sentinel_path_fifo]
keir@17849 608 os.unlink(self.sentinel_path_fifo)
keir@17849 609 except:
keir@17849 610 pass
cl349@5343 611
keir@17832 612 def setCpuid(self):
keir@17832 613 xc.domain_set_policy_cpuid(self.vm.getDomid())
keir@17832 614
keir@17832 615 if self.cpuid is not None:
keir@17832 616 cpuid = self.cpuid
keir@17832 617 transformed = {}
keir@17832 618 for sinput, regs in cpuid.iteritems():
keir@17832 619 inputs = sinput.split(',')
keir@17832 620 input = long(inputs[0])
keir@17832 621 sub_input = None
keir@17832 622 if len(inputs) == 2:
keir@17832 623 sub_input = long(inputs[1])
keir@17832 624 t = xc.domain_set_cpuid(self.vm.getDomid(),
keir@17832 625 input, sub_input, regs)
keir@17832 626 transformed[sinput] = t
keir@17832 627 self.cpuid = transformed
keir@17832 628
keir@17832 629 if self.cpuid_check is not None:
keir@17832 630 cpuid_check = self.cpuid_check
keir@17832 631 transformed = {}
keir@17832 632 for sinput, regs_check in cpuid_check.iteritems():
keir@17832 633 inputs = sinput.split(',')
keir@17832 634 input = long(inputs[0])
keir@17832 635 sub_input = None
keir@17832 636 if len(inputs) == 2:
keir@17832 637 sub_input = long(inputs[1])
keir@17832 638 t = xc.domain_check_cpuid(input, sub_input, regs_check)
keir@17832 639 transformed[sinput] = t
keir@17832 640 self.cpuid_check = transformed
keir@17832 641
keir@17832 642
ewan@12708 643
keir@16236 644 class LinuxImageHandler(ImageHandler):
keir@16236 645
keir@16236 646 ostype = "linux"
keir@16236 647 flags = 0
keir@16236 648 vhpt = 0
keir@16236 649
keir@16932 650 def configure(self, vmConfig):
keir@16932 651 ImageHandler.configure(self, vmConfig)
keir@19121 652 self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024
keir@19121 653 self.is_stubdom = (self.kernel.find('stubdom') >= 0)
keir@16932 654
keir@16236 655 def buildDomain(self):
keir@16236 656 store_evtchn = self.vm.getStorePort()
keir@16236 657 console_evtchn = self.vm.getConsolePort()
keir@16236 658
keir@16236 659 mem_mb = self.getRequiredInitialReservation() / 1024
keir@16236 660
keir@16236 661 log.debug("domid = %d", self.vm.getDomid())
keir@16236 662 log.debug("memsize = %d", mem_mb)
keir@16236 663 log.debug("image = %s", self.kernel)
keir@16236 664 log.debug("store_evtchn = %d", store_evtchn)
keir@16236 665 log.debug("console_evtchn = %d", console_evtchn)
keir@16236 666 log.debug("cmdline = %s", self.cmdline)
keir@16236 667 log.debug("ramdisk = %s", self.ramdisk)
keir@16236 668 log.debug("vcpus = %d", self.vm.getVCpuCount())
keir@16236 669 log.debug("features = %s", self.vm.getFeatures())
keir@18382 670 log.debug("flags = %d", self.flags)
keir@16236 671 if arch.type == "ia64":
keir@18382 672 log.debug("vhpt = %d", self.vhpt)
keir@16236 673
keir@16236 674 return xc.linux_build(domid = self.vm.getDomid(),
keir@16236 675 memsize = mem_mb,
keir@16236 676 image = self.kernel,
keir@16236 677 store_evtchn = store_evtchn,
keir@16236 678 console_evtchn = console_evtchn,
keir@16236 679 cmdline = self.cmdline,
keir@16236 680 ramdisk = self.ramdisk,
keir@16236 681 features = self.vm.getFeatures(),
keir@16236 682 flags = self.flags,
keir@16236 683 vhpt = self.vhpt)
keir@16236 684
keir@19121 685 def getRequiredAvailableMemory(self, mem_kb):
keir@19121 686 if self.is_stubdom :
keir@19121 687 mem_kb += self.vramsize
keir@19121 688 return mem_kb
keir@19121 689
keir@19121 690 def getRequiredInitialReservation(self):
keir@19121 691 return self.vm.getMemoryTarget()
keir@19121 692
keir@19121 693 def getRequiredMaximumReservation(self):
keir@19121 694 return self.vm.getMemoryMaximum()
keir@19121 695
keir@16236 696 def parseDeviceModelArgs(self, vmConfig):
keir@16236 697 ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
keir@16236 698 # Equivalent to old xenconsoled behaviour. Should make
keir@16236 699 # it configurable in future
keir@16236 700 ret = ret + ["-serial", "pty"]
keir@16236 701 return ret
keir@16236 702
keir@16236 703 def getDeviceModelArgs(self, restore = False):
keir@16236 704 args = ImageHandler.getDeviceModelArgs(self, restore)
keir@16236 705 args = args + ([ "-M", "xenpv"])
keir@16236 706 return args
keir@16236 707
keir@16236 708
keir@16236 709 class HVMImageHandler(ImageHandler):
keir@16236 710
keir@16236 711 ostype = "hvm"
keir@16236 712
keir@16236 713 def __init__(self, vm, vmConfig):
keir@16236 714 ImageHandler.__init__(self, vm, vmConfig)
keir@16236 715 self.shutdownWatch = None
keir@16236 716 self.rebootFeatureWatch = None
keir@16236 717
keir@16236 718 def configure(self, vmConfig):
keir@16236 719 ImageHandler.configure(self, vmConfig)
keir@16236 720
keir@16963 721 self.loader = vmConfig['platform'].get('loader')
keir@16236 722
keir@16236 723 info = xc.xeninfo()
keir@16236 724 if 'hvm' not in info['xen_caps']:
keir@16236 725 raise HVMRequired()
keir@16236 726
keir@19384 727 xen_platform_pci = int(vmConfig['platform'].get('xen_platform_pci',1))
keir@16236 728 rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
keir@16236 729
keir@19287 730 if not self.display :
keir@19287 731 self.display = ''
keir@16236 732 self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
keir@16236 733 ("image/device-model", self.device_model),
keir@16236 734 ("image/display", self.display))
keir@16857 735 self.vm.permissionsVm("image/dmargs", { 'dom': self.vm.getDomid(), 'read': True } )
keir@19384 736
keir@19384 737 if xen_platform_pci == 0:
keir@19384 738 disable_pf = 1
keir@19384 739 log.info("No need to create platform device.[domid:%d]", self.vm.getDomid())
keir@19384 740 else:
keir@19384 741 disable_pf = 0
keir@19384 742 log.info("Need to create platform device.[domid:%d]", self.vm.getDomid())
keir@19384 743
keir@19384 744 xstransact.Store("/local/domain/0/device-model/%i"%self.vm.getDomid(),
keir@19384 745 ('disable_pf', disable_pf))
keir@16236 746 self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
keir@16857 747 self.vm.permissionsVm("rtc/timeoffset", { 'dom': self.vm.getDomid(), 'read': True } )
keir@16236 748
keir@16236 749 self.apic = int(vmConfig['platform'].get('apic', 0))
keir@16236 750 self.acpi = int(vmConfig['platform'].get('acpi', 0))
alex@16474 751 self.guest_os_type = vmConfig['platform'].get('guest_os_type')
keir@19384 752
keir@17531 753
keir@16236 754 # Return a list of cmd line args to the device models based on the
keir@16236 755 # xm config file
keir@16236 756 def parseDeviceModelArgs(self, vmConfig):
keir@16236 757 ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
keir@16236 758 ret = ret + ['-vcpus', str(self.vm.getVCpuCount())]
keir@16236 759
keir@17030 760 if self.kernel:
keir@16963 761 log.debug("kernel = %s", self.kernel)
keir@16963 762 ret = ret + ['-kernel', self.kernel]
keir@16963 763 if self.ramdisk:
keir@16963 764 log.debug("ramdisk = %s", self.ramdisk)
keir@16963 765 ret = ret + ['-initrd', self.ramdisk]
keir@16963 766 if self.cmdline:
keir@16963 767 log.debug("cmdline = %s", self.cmdline)
keir@16963 768 ret = ret + ['-append', self.cmdline]
keir@16963 769
keir@16963 770
keir@16236 771 dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
keir@16236 772 'localtime', 'serial', 'stdvga', 'isa',
keir@17082 773 'acpi', 'usb', 'usbdevice' ]
keir@16236 774
keir@16236 775 for a in dmargs:
keir@16236 776 v = vmConfig['platform'].get(a)
keir@16236 777
keir@16236 778 # python doesn't allow '-' in variable names
keir@16236 779 if a == 'stdvga': a = 'std-vga'
keir@16236 780 if a == 'keymap': a = 'k'
keir@16236 781
keir@16236 782 # Handle booleans gracefully
keir@16236 783 if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']:
keir@16236 784 try:
keir@16236 785 if v != None: v = int(v)
keir@16236 786 if v: ret.append("-%s" % a)
keir@16236 787 except (ValueError, TypeError):
keir@16236 788 pass # if we can't convert it to a sane type, ignore it
keir@19484 789 elif a == 'serial':
keir@19484 790 if v:
keir@19484 791 if type(v) == str:
keir@19484 792 v = [v]
keir@19484 793 for s in v:
keir@19484 794 if s:
keir@19484 795 ret.append("-serial")
keir@19484 796 ret.append("%s" % s)
keir@16236 797 else:
keir@16236 798 if v:
keir@16236 799 ret.append("-%s" % a)
keir@16236 800 ret.append("%s" % v)
keir@16236 801
keir@16236 802 if a in ['fda', 'fdb']:
keir@16236 803 if v:
keir@16236 804 if not os.path.isabs(v):
keir@16236 805 raise VmError("Floppy file %s does not exist." % v)
keir@16236 806 log.debug("args: %s, val: %s" % (a,v))
keir@16236 807
keir@16236 808 # Handle disk/network related options
keir@16236 809 mac = None
keir@16236 810 nics = 0
keir@16236 811
keir@16236 812 for devuuid in vmConfig['vbd_refs']:
keir@16236 813 devinfo = vmConfig['devices'][devuuid][1]
keir@16236 814 uname = devinfo.get('uname')
keir@16236 815 if uname is not None and 'file:' in uname:
keir@16236 816 (_, vbdparam) = string.split(uname, ':', 1)
keir@16236 817 if not os.path.isfile(vbdparam):
keir@16236 818 raise VmError('Disk image does not exist: %s' %
keir@16236 819 vbdparam)
keir@16236 820
keir@16236 821 for devuuid in vmConfig['vif_refs']:
keir@16236 822 devinfo = vmConfig['devices'][devuuid][1]
keir@16236 823 dtype = devinfo.get('type', 'ioemu')
keir@16236 824 if dtype != 'ioemu':
keir@16236 825 continue
keir@16236 826 nics += 1
keir@16236 827 mac = devinfo.get('mac')
keir@16236 828 if mac is None:
keir@16236 829 raise VmError("MAC address not specified or generated.")
keir@16236 830 bridge = devinfo.get('bridge', 'xenbr0')
keir@16236 831 model = devinfo.get('model', 'rtl8139')
keir@16236 832 ret.append("-net")
keir@16236 833 ret.append("nic,vlan=%d,macaddr=%s,model=%s" %
keir@16236 834 (nics, mac, model))
keir@16236 835 ret.append("-net")
keir@17225 836 ret.append("tap,vlan=%d,ifname=tap%d.%d,bridge=%s" %
keir@17225 837 (nics, self.vm.getDomid(), nics-1, bridge))
keir@16236 838
keir@18262 839 if nics == 0:
keir@18262 840 ret.append("-net")
keir@18262 841 ret.append("none")
keir@18262 842
keir@16236 843 return ret
keir@16236 844
keir@16236 845 def getDeviceModelArgs(self, restore = False):
keir@16236 846 args = ImageHandler.getDeviceModelArgs(self, restore)
keir@16236 847 args = args + ([ "-M", "xenfv"])
keir@16236 848 if restore:
keir@16236 849 args = args + ([ "-loadvm", "/var/lib/xen/qemu-save.%d" %
keir@16236 850 self.vm.getDomid() ])
keir@16236 851 return args
keir@16236 852
keir@16236 853 def buildDomain(self):
keir@16236 854 store_evtchn = self.vm.getStorePort()
keir@16236 855
keir@18977 856 memmax_mb = self.getRequiredMaximumReservation() / 1024
keir@16236 857 mem_mb = self.getRequiredInitialReservation() / 1024
keir@16236 858
keir@16236 859 log.debug("domid = %d", self.vm.getDomid())
keir@16963 860 log.debug("image = %s", self.loader)
keir@16236 861 log.debug("store_evtchn = %d", store_evtchn)
keir@18977 862 log.debug("memsize = %d", memmax_mb)
keir@18977 863 log.debug("target = %d", mem_mb)
keir@16236 864 log.debug("vcpus = %d", self.vm.getVCpuCount())
keir@16236 865 log.debug("acpi = %d", self.acpi)
keir@16236 866 log.debug("apic = %d", self.apic)
keir@16236 867
keir@16236 868 rc = xc.hvm_build(domid = self.vm.getDomid(),
keir@16963 869 image = self.loader,
keir@18977 870 memsize = memmax_mb,
keir@18977 871 target = mem_mb,
keir@16236 872 vcpus = self.vm.getVCpuCount(),
keir@16236 873 acpi = self.acpi,
keir@16236 874 apic = self.apic)
keir@16236 875 rc['notes'] = { 'SUSPEND_CANCEL': 1 }
keir@16236 876
keir@16236 877 rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
keir@16236 878 HVM_PARAM_STORE_PFN)
keir@16236 879 xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN,
keir@16236 880 store_evtchn)
keir@16236 881
keir@16236 882 return rc
keir@16236 883
keir@16236 884
ewan@11340 885 class IA64_HVM_ImageHandler(HVMImageHandler):
emellor@7056 886
keir@16157 887 def configure(self, vmConfig):
keir@16157 888 HVMImageHandler.configure(self, vmConfig)
keir@16157 889 self.vhpt = int(vmConfig['platform'].get('vhpt', 0))
keir@19037 890 self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024
keir@16157 891
kfraser@15187 892 def buildDomain(self):
kfraser@15187 893 xc.nvram_init(self.vm.getName(), self.vm.getDomid())
keir@16157 894 xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_VHPT_SIZE, self.vhpt)
alex@16477 895 if self.guest_os_type is not None:
alex@16477 896 xc.set_os_type(self.guest_os_type.lower(), self.vm.getDomid())
kfraser@15187 897 return HVMImageHandler.buildDomain(self)
kfraser@15187 898
ewan@11425 899 def getRequiredAvailableMemory(self, mem_kb):
ewan@11340 900 page_kb = 16
alex@15128 901 # ROM size for guest firmware, io page, xenstore page
alex@15128 902 # buffer io page, buffer pio page and memmap info page
alex@15128 903 extra_pages = 1024 + 5
keir@17522 904 mem_kb += extra_pages * page_kb
keir@19037 905 mem_kb += self.vramsize
keir@19037 906 return mem_kb
emellor@7056 907
awilliam@13124 908 def getRequiredInitialReservation(self):
awilliam@13124 909 return self.vm.getMemoryTarget()
awilliam@13124 910
awilliam@11447 911 def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
ewan@11340 912 # Explicit shadow memory is not a concept
ewan@11340 913 return 0
ewan@11340 914
keir@16236 915 def getDeviceModelArgs(self, restore = False):
keir@16236 916 args = HVMImageHandler.getDeviceModelArgs(self, restore)
keir@16236 917 args = args + ([ "-m", "%s" %
keir@16236 918 (self.getRequiredInitialReservation() / 1024) ])
keir@16236 919 return args
keir@16236 920
keir@17656 921 def setCpuid(self):
keir@17656 922 # Guest CPUID configuration is not implemented yet.
keir@17656 923 return
keir@16236 924
keir@16157 925 class IA64_Linux_ImageHandler(LinuxImageHandler):
keir@16157 926
keir@16157 927 def configure(self, vmConfig):
keir@16157 928 LinuxImageHandler.configure(self, vmConfig)
keir@16157 929 self.vhpt = int(vmConfig['platform'].get('vhpt', 0))
keir@16157 930
keir@17832 931 def setCpuid(self):
keir@17832 932 # Guest CPUID configuration is not implemented yet.
keir@17832 933 return
keir@16157 934
ewan@11340 935 class X86_HVM_ImageHandler(HVMImageHandler):
ewan@11340 936
keir@16137 937 def configure(self, vmConfig):
keir@16137 938 HVMImageHandler.configure(self, vmConfig)
keir@16137 939 self.pae = int(vmConfig['platform'].get('pae', 0))
keir@19037 940 self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024
keir@16137 941
keir@16137 942 def buildDomain(self):
keir@16137 943 xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_PAE_ENABLED, self.pae)
keir@17832 944 rc = HVMImageHandler.buildDomain(self)
keir@17531 945 self.setCpuid()
keir@17832 946 return rc
keir@16137 947
ewan@11425 948 def getRequiredAvailableMemory(self, mem_kb):
keir@19037 949 return mem_kb + self.vramsize
ewan@11430 950
kfraser@12218 951 def getRequiredInitialReservation(self):
kfraser@12218 952 return self.vm.getMemoryTarget()
ewan@11340 953
kfraser@12994 954 def getRequiredMaximumReservation(self):
kfraser@12994 955 return self.vm.getMemoryMaximum()
kfraser@12994 956
ewan@11425 957 def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
Tim@12198 958 # 256 pages (1MB) per vcpu,
Tim@12198 959 # plus 1 page per MiB of RAM for the P2M map,
Tim@12198 960 # plus 1 page per MiB of RAM to shadow the resident processes.
Tim@12198 961 # This is higher than the minimum that Xen would allocate if no value
Tim@12198 962 # were given (but the Xen minimum is for safety, not performance).
Tim@12198 963 return max(4 * (256 * self.vm.getVCpuCount() + 2 * (maxmem_kb / 1024)),
ewan@11425 964 shadow_mem_kb)
ewan@11425 965
Tim@15646 966
kfraser@12872 967 class X86_Linux_ImageHandler(LinuxImageHandler):
kfraser@12872 968
kfraser@12872 969 def buildDomain(self):
kfraser@12872 970 # set physical mapping limit
kfraser@12872 971 # add an 8MB slack to balance backend allocations.
kfraser@12994 972 mem_kb = self.getRequiredMaximumReservation() + (8 * 1024)
kfraser@12872 973 xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb)
keir@17832 974 rc = LinuxImageHandler.buildDomain(self)
keir@17832 975 self.setCpuid()
keir@17832 976 return rc
ewan@11340 977
ewan@11340 978 _handlers = {
ewan@11340 979 "ia64": {
keir@16157 980 "linux": IA64_Linux_ImageHandler,
ewan@11340 981 "hvm": IA64_HVM_ImageHandler,
ewan@11340 982 },
ewan@11340 983 "x86": {
kfraser@12872 984 "linux": X86_Linux_ImageHandler,
ewan@11340 985 "hvm": X86_HVM_ImageHandler,
ewan@11340 986 },
ewan@11340 987 }
emellor@7056 988
emellor@7056 989 def findImageHandlerClass(image):
emellor@7056 990 """Find the image handler class for an image config.
emellor@7056 991
emellor@7056 992 @param image config
emellor@7056 993 @return ImageHandler subclass or None
emellor@7056 994 """
ewan@14361 995 image_type = image.image_type()
ewan@11340 996 try:
atse@12686 997 return _handlers[arch.type][image_type]
ewan@11340 998 except KeyError:
atse@12686 999 raise VmError('unknown image type: ' + image_type)