📄 image.py
字号:
#============================================================================# This library is free software; you can redistribute it and/or# modify it under the terms of version 2.1 of the GNU Lesser General Public# License as published by the Free Software Foundation.## This library is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU# Lesser General Public License for more details.## You should have received a copy of the GNU Lesser General Public# License along with this library; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#============================================================================# Copyright (C) 2005 Mike Wray <mike.wray@hp.com># Copyright (C) 2005-2007 XenSource Ltd#============================================================================import os, os.path, stringimport reimport mathimport timeimport signalimport threadimport fcntlimport sysimport errnoimport globimport tracebackimport xen.lowlevel.xcfrom xen.xend.XendConstants import *from xen.xend.XendError import VmError, XendError, HVMRequiredfrom xen.xend.XendLogging import logfrom xen.xend.XendOptions import instance as xenoptsfrom xen.xend.xenstore.xstransact import xstransactfrom xen.xend.xenstore.xswatch import xswatchfrom xen.xend import archfrom xen.xend import XendOptionsfrom xen.util import oshelpfrom xen.util import utilsxc = xen.lowlevel.xc.xc()MAX_GUEST_CMDLINE = 1024sentinel_path_prefix = '/var/run/xend/dm-'sentinel_fifos_inuse = { }def cleanup_stale_sentinel_fifos(): for path in glob.glob(sentinel_path_prefix + '*.fifo'): if path in sentinel_fifos_inuse: continue try: os.unlink(path) except OSError, e: log.warning('could not delete stale fifo %s: %s', path, utils.exception_string(e))def create(vm, vmConfig): """Create an image handler for a vm. @return ImageHandler instance """ return findImageHandlerClass(vmConfig)(vm, vmConfig)class ImageHandler: """Abstract base class for image handlers. createImage() is called to configure and build the domain from its kernel image and ramdisk etc. The method buildDomain() is used to build the domain, and must be defined in a subclass. Usually this is the only method that needs defining in a subclass. The method createDeviceModel() is called to create the domain device model. The method destroyDeviceModel() is called to reap the device model """ ostype = None def __init__(self, vm, vmConfig): self.vm = vm self.bootloader = False self.kernel = None self.ramdisk = None self.cmdline = None self.configure(vmConfig) def configure(self, vmConfig): """Config actions common to all unix-like domains.""" if '_temp_using_bootloader' in vmConfig: self.bootloader = True self.kernel = vmConfig['_temp_kernel'] self.cmdline = vmConfig['_temp_args'] self.ramdisk = vmConfig['_temp_ramdisk'] else: self.kernel = vmConfig['PV_kernel'] self.cmdline = vmConfig['PV_args'] self.ramdisk = vmConfig['PV_ramdisk'] self.vm.storeVm(("image/ostype", self.ostype), ("image/kernel", self.kernel), ("image/cmdline", self.cmdline), ("image/ramdisk", self.ramdisk)) self.vm.permissionsVm("image/cmdline", { 'dom': self.vm.getDomid(), 'read': True } ) self.device_model = vmConfig['platform'].get('device_model') self.display = vmConfig['platform'].get('display') self.xauthority = vmConfig['platform'].get('xauthority') self.vncconsole = int(vmConfig['platform'].get('vncconsole', 0)) self.dmargs = self.parseDeviceModelArgs(vmConfig) self.pid = None rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset') if rtc_timeoffset is not None: xc.domain_set_time_offset(self.vm.getDomid(), int(rtc_timeoffset)) self.cpuid = None self.cpuid_check = None if 'cpuid' in vmConfig: self.cpuid = vmConfig['cpuid']; if 'cpuid_check' in vmConfig: self.cpuid_check = vmConfig['cpuid_check'] def cleanupBootloading(self): if self.bootloader: self.unlink(self.kernel) self.unlink(self.ramdisk) def unlink(self, f): if not f: return try: os.unlink(f) except OSError, ex: log.warning("error removing bootloader file '%s': %s", f, ex) def createImage(self): """Entry point to create domain memory image. Override in subclass if needed. """ return self.createDomain() def createDomain(self): """Build the domain boot image. """ # Set params and call buildDomain(). if self.kernel and not os.path.isfile(self.kernel): raise VmError('Kernel image does not exist: %s' % self.kernel) if self.ramdisk and not os.path.isfile(self.ramdisk): raise VmError('Kernel ramdisk does not exist: %s' % self.ramdisk) if len(self.cmdline) >= MAX_GUEST_CMDLINE: log.warning('kernel cmdline too long, domain %d', self.vm.getDomid()) log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype, self.vm.getDomid(), self.vm.getVCpuCount()) result = self.buildDomain() if isinstance(result, dict): return result else: raise VmError('Building domain failed: ostype=%s dom=%d err=%s' % (self.ostype, self.vm.getDomid(), str(result))) def getRequiredAvailableMemory(self, mem_kb): """@param mem_kb The configured maxmem or memory, in KiB. @return The corresponding required amount of memory for the domain, also in KiB. This is normally the given mem_kb, but architecture- or image-specific code may override this to add headroom where necessary.""" return mem_kb def getRequiredInitialReservation(self): """@param mem_kb The configured memory, in KiB. @return The corresponding required amount of memory to be free, also in KiB. This is normally the same as getRequiredAvailableMemory, but architecture- or image-specific code may override this to add headroom where necessary.""" return self.getRequiredAvailableMemory(self.vm.getMemoryTarget()) def getRequiredMaximumReservation(self): """@param mem_kb The maximum possible memory, in KiB. @return The corresponding required amount of memory to be free, also in KiB. This is normally the same as getRequiredAvailableMemory, but architecture- or image-specific code may override this to add headroom where necessary.""" return self.getRequiredAvailableMemory(self.vm.getMemoryMaximum()) def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb): """@param shadow_mem_kb The configured shadow memory, in KiB. @param maxmem_kb The configured maxmem, in KiB. @return The corresponding required amount of shadow memory, also in KiB.""" # PV domains don't need any shadow memory return 0 def buildDomain(self): """Build the domain. Define in subclass.""" raise NotImplementedError() def prepareEnvironment(self): """Prepare the environment for the execution of the domain. This method is called before any devices are set up.""" domid = self.vm.getDomid() # Delete left-over pipes try: os.unlink('/var/run/tap/qemu-read-%d' % domid) os.unlink('/var/run/tap/qemu-write-%d' % domid) except: pass # No device model, don't create pipes if self.device_model is None: return # If we use a device model, the pipes for communication between # blktapctrl and ioemu must be present before the devices are # created (blktapctrl must access them for new block devices) # mkdir throws an exception if the path already exists try: os.mkdir('/var/run/tap', 0755) except: pass try: os.mkfifo('/var/run/tap/qemu-read-%d' % domid, 0600) os.mkfifo('/var/run/tap/qemu-write-%d' % domid, 0600) except OSError, e: log.warn('Could not create blktap pipes for domain %d' % domid) log.exception(e) pass # Return a list of cmd line args to the device models based on the # xm config file def parseDeviceModelArgs(self, vmConfig): ret = ["-domain-name", str(self.vm.info['name_label'])] # Find RFB console device, and if it exists, make QEMU enable # the VNC console. if int(vmConfig['platform'].get('nographic', 0)) != 0: # skip vnc init if nographic is set ret.append('-nographic') return ret vnc_config = {} has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0 has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0 opengl = 1 keymap = vmConfig['platform'].get("keymap") for dev_uuid in vmConfig['console_refs']: dev_type, dev_info = vmConfig['devices'][dev_uuid] if dev_type == 'vfb': if 'keymap' in dev_info: keymap = dev_info.get('keymap',{}) vfb_type = dev_info.get('type', {}) if vfb_type == 'sdl': self.display = dev_info.get('display', {}) self.xauthority = dev_info.get('xauthority', {}) opengl = int(dev_info.get('opengl', opengl)) has_sdl = True else: vnc_config = dev_info.get('other_config', {}) has_vnc = True break if keymap: ret.append("-k") ret.append(keymap) if has_vnc: if not vnc_config: for key in ('vncunused', 'vnclisten', 'vncdisplay', 'vncpasswd'): if key in vmConfig['platform']: vnc_config[key] = vmConfig['platform'][key] if vnc_config.has_key("vncpasswd"): passwd = vnc_config["vncpasswd"] else: passwd = XendOptions.instance().get_vncpasswd_default() vncopts = "" if passwd: self.vm.storeVm("vncpasswd", passwd) self.vm.permissionsVm("vncpasswd", { 'dom': self.vm.getDomid(), 'read': True } ) vncopts = vncopts + ",password" log.debug("Stored a VNC password for vfb access") else: log.debug("No VNC passwd configured for vfb access") if XendOptions.instance().get_vnc_tls(): vncx509certdir = XendOptions.instance().get_vnc_x509_cert_dir() vncx509verify = XendOptions.instance().get_vnc_x509_verify() if not os.path.exists(vncx509certdir): raise VmError("VNC x509 certificate dir %s does not exist" % vncx509certdir) if vncx509verify:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -