📄 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 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 XendOptionsxc = xen.lowlevel.xc.xc()MAX_GUEST_CMDLINE = 1024def 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.device_model = vmConfig['platform'].get('device_model') self.display = vmConfig['platform'].get('display') self.xauthority = vmConfig['platform'].get('xauthority') self.vncconsole = vmConfig['platform'].get('vncconsole') self.dmargs = self.parseDeviceModelArgs(vmConfig) self.pid = None 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 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() # 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 for dev_uuid in vmConfig['console_refs']: dev_type, dev_info = vmConfig['devices'][dev_uuid] if dev_type == 'vfb': vfb_type = dev_info.get('type', {}) if vfb_type == 'sdl': self.display = dev_info.get('display', {}) self.xauthority = dev_info.get('xauthority', {}) has_sdl = True else: vnc_config = dev_info.get('other_config', {}) has_vnc = True break keymap = vmConfig['platform'].get("keymap") 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) 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: vncopts = vncopts + ",tls,x509verify=%s" % vncx509certdir else: vncopts = vncopts + ",tls,x509=%s" % vncx509certdir vnclisten = vnc_config.get('vnclisten', XendOptions.instance().get_vnclisten_address()) vncdisplay = vnc_config.get('vncdisplay', 0) ret.append('-vnc') ret.append("%s:%s%s" % (vnclisten, vncdisplay, vncopts)) if vnc_config.get('vncunused', 0): ret.append('-vncunused') elif has_sdl: # SDL is default in QEMU. pass else: ret.append('-nographic') if int(vmConfig['platform'].get('monitor', 0)) != 0: ret = ret + ['-monitor', 'vc'] return ret def getDeviceModelArgs(self, restore = False): args = [self.device_model] args = args + ([ "-d", "%d" % self.vm.getDomid() ]) args = args + self.dmargs return args def createDeviceModel(self, restore = False): if self.device_model is None: return if self.pid: return # Execute device model. #todo: Error handling args = self.getDeviceModelArgs(restore) env = dict(os.environ) if self.display: env['DISPLAY'] = self.display if self.xauthority: env['XAUTHORITY'] = self.xauthority if self.vncconsole: args = args + ([ "-vncviewer" ]) log.info("spawning device models: %s %s", self.device_model, args) # keep track of pid and spawned options to kill it later self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env) self.vm.storeDom("image/device-model-pid", self.pid) log.info("device model pid: %d", self.pid) def saveDeviceModel(self): if self.device_model is None: return # Signal the device model to pause itself and save its state xstransact.Store("/local/domain/0/device-model/%i" % self.vm.getDomid(), ('command', 'save')) # Wait for confirmation. Could do this with a watch but we'd # still end up spinning here waiting for the watch to fire. state = '' count = 0 while state != 'paused': state = xstransact.Read("/local/domain/0/device-model/%i/state" % self.vm.getDomid()) time.sleep(0.1) count += 1 if count > 100: raise VmError('Timed out waiting for device model to save') def resumeDeviceModel(self): if self.device_model is None: return # Signal the device model to resume activity after pausing to save. xstransact.Store("/local/domain/0/device-model/%i" % self.vm.getDomid(), ('command', 'continue')) def recreate(self): if self.device_model is None: return self.pid = self.vm.gatherDom(('image/device-model-pid', int)) def destroyDeviceModel(self): if self.device_model is None:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -