mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
bitkeeper revision 1.1662.1.7 (42a47555156iGoOjUyZtvbuMFZHXkg)
XendDomainInfo.py: Move guest image handling into seperate file. image.py: new file Signed-off-by: Mike Wray <mike.wray@hp.com> Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
This commit is contained in:
1 parent
12f5438d72
commit
d5affeab6a
3 files changed
+376
-252
No files matched your search
@@ -114,25 +114,6 @@ def get_config_handler(name):
|
||||
"""
|
||||
return config_handlers.get(name)
|
||||
|
||||
"""Table of handlers for virtual machine images.
|
||||
Indexed by image type.
|
||||
"""
|
||||
image_handlers = {}
|
||||
|
||||
def add_image_handler(name, h):
|
||||
"""Add a handler for an image type
|
||||
@param name: image type
|
||||
@param h: handler: fn(config, name, memory, image)
|
||||
"""
|
||||
image_handlers[name] = h
|
||||
|
||||
def get_image_handler(name):
|
||||
"""Get the handler for an image type.
|
||||
@param name: image type
|
||||
@return: handler or None
|
||||
"""
|
||||
return image_handlers.get(name)
|
||||
|
||||
"""Table of handlers for devices.
|
||||
Indexed by device type.
|
||||
"""
|
||||
@@ -252,8 +233,6 @@ class XendDomainInfo:
|
||||
self.name = None
|
||||
self.memory = None
|
||||
self.image = None
|
||||
self.ramdisk = None
|
||||
self.cmdline = None
|
||||
|
||||
self.channel = None
|
||||
self.controllers = {}
|
||||
@@ -278,8 +257,6 @@ class XendDomainInfo:
|
||||
|
||||
self.console_port = None
|
||||
self.savedinfo = None
|
||||
self.image_handler = None
|
||||
self.is_vmx = False
|
||||
self.vcpus = 1
|
||||
self.bootloader = None
|
||||
|
||||
@@ -330,8 +307,6 @@ class XendDomainInfo:
|
||||
console = self.getConsole()
|
||||
if console:
|
||||
s += " console=" + str(console.console_port)
|
||||
if self.image:
|
||||
s += " image=" + self.image
|
||||
s += ""
|
||||
return s
|
||||
|
||||
@@ -484,8 +459,8 @@ class XendDomainInfo:
|
||||
# Initial domain create.
|
||||
self.setName(sxp.child_value(config, 'name'))
|
||||
self.check_name(self.name)
|
||||
self.init_image()
|
||||
self.configure_cpus(config)
|
||||
self.find_image_handler()
|
||||
self.init_domain()
|
||||
self.register_domain()
|
||||
self.configure_bootloader()
|
||||
@@ -527,29 +502,24 @@ class XendDomainInfo:
|
||||
except:
|
||||
raise VmError('invalid vcpus value')
|
||||
|
||||
def find_image_handler(self):
|
||||
"""Construct the boot image for the domain.
|
||||
|
||||
@return vm
|
||||
def init_image(self):
|
||||
"""Create boot image handler for the domain.
|
||||
"""
|
||||
image = sxp.child_value(self.config, 'image')
|
||||
if image is None:
|
||||
raise VmError('missing image')
|
||||
image_name = sxp.name(image)
|
||||
if image_name is None:
|
||||
raise VmError('missing image name')
|
||||
if image_name == "vmx":
|
||||
self.is_vmx = True
|
||||
image_handler = get_image_handler(image_name)
|
||||
if image_handler is None:
|
||||
raise VmError('unknown image type: ' + image_name)
|
||||
self.image_handler = image_handler
|
||||
return self
|
||||
self.image = ImageHandler.create(self, image)
|
||||
|
||||
def construct_image(self):
|
||||
image = sxp.child_value(self.config, 'image')
|
||||
self.image_handler(self, image)
|
||||
return self
|
||||
"""Construct the boot image for the domain.
|
||||
"""
|
||||
self.create_channel()
|
||||
self.image.createImage()
|
||||
#self.image.exportToDB()
|
||||
#if self.store_channel:
|
||||
# self.db.introduceDomain(self.id,
|
||||
# self.store_mfn,
|
||||
# self.store_channel)
|
||||
|
||||
def config_devices(self, name):
|
||||
"""Get a list of the 'device' nodes of a given type from the config.
|
||||
@@ -596,7 +566,7 @@ class XendDomainInfo:
|
||||
"""Completely destroy the vm.
|
||||
"""
|
||||
self.cleanup()
|
||||
return self.destroy_domain()
|
||||
self.destroy_domain()
|
||||
|
||||
def destroy_domain(self):
|
||||
"""Destroy the vm's domain.
|
||||
@@ -606,9 +576,15 @@ class XendDomainInfo:
|
||||
if self.channel:
|
||||
self.channel.close()
|
||||
self.channel = None
|
||||
if self.image:
|
||||
try:
|
||||
self.image.destroy()
|
||||
self.image = None
|
||||
except:
|
||||
pass
|
||||
if self.id is None: return 0
|
||||
try:
|
||||
return xc.domain_destroy(dom=self.id)
|
||||
xc.domain_destroy(dom=self.id)
|
||||
except Exception, err:
|
||||
log.exception("Domain destroy failed: %s", self.name)
|
||||
|
||||
@@ -661,80 +637,11 @@ class XendDomainInfo:
|
||||
cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
|
||||
except:
|
||||
raise VmError('invalid cpu')
|
||||
cpu_weight = self.cpu_weight
|
||||
memory = memory * 1024 + self.pgtable_size(memory)
|
||||
dom = xc.domain_create(dom= dom)
|
||||
if self.bootloader:
|
||||
try:
|
||||
if kernel: os.unlink(kernel)
|
||||
if ramdisk: os.unlink(ramdisk)
|
||||
except OSError, e:
|
||||
log.warning('unable to unlink kernel/ramdisk: %s' %(e,))
|
||||
|
||||
if dom <= 0:
|
||||
raise VmError('Creating domain failed: name=%s memory=%d'
|
||||
% (self.name, memory))
|
||||
xc.domain_setcpuweight(dom, cpu_weight)
|
||||
xc.domain_setmaxmem(dom, memory)
|
||||
xc.domain_memory_increase_reservation(dom, memory)
|
||||
if cpu != -1:
|
||||
xc.domain_pincpu(dom, 0, 1<<int(cpu))
|
||||
log.debug('init_domain> Created domain=%d name=%s memory=%d', dom, self.name, memory)
|
||||
self.setdom(dom)
|
||||
|
||||
def build_domain(self, ostype, kernel, ramdisk, cmdline, memmap):
|
||||
"""Build the domain boot image.
|
||||
"""
|
||||
if self.recreate or self.restore: return
|
||||
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)
|
||||
if len(cmdline) >= 256:
|
||||
log.warning('kernel cmdline too long, domain %d', self.id)
|
||||
dom = self.id
|
||||
buildfn = getattr(xc, '%s_build' % ostype)
|
||||
flags = 0
|
||||
if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
|
||||
if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
|
||||
#todo generalise this
|
||||
if ostype == "vmx":
|
||||
log.debug('building vmx domain')
|
||||
err = buildfn(dom = dom,
|
||||
image = kernel,
|
||||
control_evtchn = 0,
|
||||
memsize = self.memory,
|
||||
memmap = memmap,
|
||||
cmdline = cmdline,
|
||||
ramdisk = ramdisk,
|
||||
flags = flags)
|
||||
else:
|
||||
log.debug('building dom with %d vcpus', self.vcpus)
|
||||
err = buildfn(dom = dom,
|
||||
image = kernel,
|
||||
control_evtchn = self.channel.getRemotePort(),
|
||||
cmdline = cmdline,
|
||||
ramdisk = ramdisk,
|
||||
flags = flags,
|
||||
vcpus = self.vcpus)
|
||||
if err != 0:
|
||||
raise VmError('Building domain failed: type=%s dom=%d err=%d'
|
||||
% (ostype, dom, err))
|
||||
|
||||
def create_domain(self, ostype, kernel, ramdisk, cmdline, memmap=''):
|
||||
"""Create a domain. Builds the image but does not configure it.
|
||||
|
||||
@param ostype: OS type
|
||||
@param kernel: kernel image
|
||||
@param ramdisk: kernel ramdisk
|
||||
@param cmdline: kernel commandline
|
||||
"""
|
||||
|
||||
self.create_channel()
|
||||
self.build_domain(ostype, kernel, ramdisk, cmdline, memmap)
|
||||
self.image = kernel
|
||||
self.ramdisk = ramdisk
|
||||
self.cmdline = cmdline
|
||||
dom = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight)
|
||||
log.debug('init_domain> Created domain=%d name=%s memory=%d',
|
||||
dom, self.name, self.memory)
|
||||
if not self.restore:
|
||||
self.setdom(dom)
|
||||
|
||||
def create_channel(self):
|
||||
"""Create the control channel to the domain.
|
||||
@@ -773,43 +680,6 @@ class XendDomainInfo:
|
||||
ctrl.initController(reboot=True)
|
||||
else:
|
||||
self.create_configured_devices()
|
||||
if self.is_vmx:
|
||||
self.create_vmx_model()
|
||||
|
||||
def create_vmx_model(self):
|
||||
#todo: remove special case for vmx
|
||||
device_model = sxp.child_value(self.config, 'device_model')
|
||||
if not device_model:
|
||||
raise VmError("vmx: missing device model")
|
||||
device_config = sxp.child_value(self.config, 'device_config')
|
||||
if not device_config:
|
||||
raise VmError("vmx: missing device config")
|
||||
#todo: self.memory?
|
||||
memory = sxp.child_value(self.config, "memory")
|
||||
# Create an event channel
|
||||
device_channel = channel.eventChannel(0, self.id)
|
||||
# see if a vncviewer was specified
|
||||
# XXX RN: bit of a hack. should unify this, maybe stick in config space
|
||||
vncconnect=""
|
||||
image = sxp.child_value(self.config, "image")
|
||||
args = sxp.child_value(image, "args")
|
||||
if args:
|
||||
arg_list = string.split(args)
|
||||
for arg in arg_list:
|
||||
al = string.split(arg, '=')
|
||||
if al[0] == "VNC_VIEWER":
|
||||
vncconnect=" -v %s" % al[1]
|
||||
break
|
||||
|
||||
# Execute device model.
|
||||
#todo: Error handling
|
||||
# XXX RN: note that the order of args matter!
|
||||
os.system(device_model
|
||||
+ " -f %s" % device_config
|
||||
+ vncconnect
|
||||
+ " -d %d" % self.id
|
||||
+ " -p %d" % device_channel['port1']
|
||||
+ " -m %s" % memory)
|
||||
|
||||
def device_create(self, dev_config):
|
||||
"""Create a new device.
|
||||
@@ -862,9 +732,7 @@ class XendDomainInfo:
|
||||
def configure_bootloader(self):
|
||||
"""Configure boot loader.
|
||||
"""
|
||||
bl = sxp.child_value(self.config, "bootloader")
|
||||
if bl is not None:
|
||||
self.bootloader = bl
|
||||
self.bootloader = sxp.child_value(self.config, "bootloader")
|
||||
|
||||
def configure_console(self):
|
||||
"""Configure the vm console port.
|
||||
@@ -1052,19 +920,6 @@ class XendDomainInfo:
|
||||
log.warning("Unknown config field %s", field_name)
|
||||
index[field_name] = field_index + 1
|
||||
|
||||
def pgtable_size(self, memory):
|
||||
"""Return the size of memory needed for 1:1 page tables for physical
|
||||
mode.
|
||||
|
||||
@param memory: size in MB
|
||||
@return size in KB
|
||||
"""
|
||||
if self.is_vmx:
|
||||
# Logic x86-32 specific.
|
||||
# 1 page for the PGD + 1 pte page for 4MB of memory (rounded)
|
||||
return (1 + ((memory + 3) >> 2)) * 4
|
||||
return 0
|
||||
|
||||
def mem_target_set(self, target):
|
||||
"""Set domain memory target in pages.
|
||||
"""
|
||||
@@ -1091,83 +946,6 @@ class XendDomainInfo:
|
||||
return 0
|
||||
return timeout - (time.time() - self.shutdown_pending['start'])
|
||||
|
||||
def vm_image_linux(vm, image):
|
||||
"""Create a VM for a linux image.
|
||||
|
||||
@param name: vm name
|
||||
@param memory: vm memory
|
||||
@param image: image config
|
||||
@return: vm
|
||||
"""
|
||||
kernel = sxp.child_value(image, "kernel")
|
||||
cmdline = ""
|
||||
ip = sxp.child_value(image, "ip", None)
|
||||
if ip:
|
||||
cmdline += " ip=" + ip
|
||||
root = sxp.child_value(image, "root")
|
||||
if root:
|
||||
cmdline += " root=" + root
|
||||
args = sxp.child_value(image, "args")
|
||||
if args:
|
||||
cmdline += " " + args
|
||||
ramdisk = sxp.child_value(image, "ramdisk", '')
|
||||
log.debug("creating linux domain with cmdline: %s" %(cmdline,))
|
||||
vm.create_domain("linux", kernel, ramdisk, cmdline)
|
||||
return vm
|
||||
|
||||
def vm_image_plan9(vm, image):
|
||||
"""Create a VM for a Plan 9 image.
|
||||
|
||||
name vm name
|
||||
memory vm memory
|
||||
image image config
|
||||
|
||||
returns vm
|
||||
"""
|
||||
kernel = sxp.child_value(image, "kernel")
|
||||
cmdline = ""
|
||||
ip = sxp.child_value(image, "ip", "dhcp")
|
||||
if ip:
|
||||
cmdline += "ip=" + ip
|
||||
root = sxp.child_value(image, "root")
|
||||
if root:
|
||||
cmdline += "root=" + root
|
||||
args = sxp.child_value(image, "args")
|
||||
if args:
|
||||
cmdline += " " + args
|
||||
ramdisk = sxp.child_value(image, "ramdisk", '')
|
||||
log.debug("creating plan9 domain with cmdline: %s" %(cmdline,))
|
||||
vm.create_domain("plan9", kernel, ramdisk, cmdline)
|
||||
return vm
|
||||
|
||||
def vm_image_vmx(vm, image):
|
||||
"""Create a VM for the VMX environment.
|
||||
|
||||
@param name: vm name
|
||||
@param memory: vm memory
|
||||
@param image: image config
|
||||
@return: vm
|
||||
"""
|
||||
kernel = sxp.child_value(image, "kernel")
|
||||
cmdline = ""
|
||||
ip = sxp.child_value(image, "ip", "dhcp")
|
||||
if ip:
|
||||
cmdline += " ip=" + ip
|
||||
root = sxp.child_value(image, "root")
|
||||
if root:
|
||||
cmdline += " root=" + root
|
||||
args = sxp.child_value(image, "args")
|
||||
if args:
|
||||
cmdline += " " + args
|
||||
ramdisk = sxp.child_value(image, "ramdisk", '')
|
||||
memmap = sxp.child_value(vm.config, "memmap", '')
|
||||
memmap = sxp.parse(open(memmap))[0]
|
||||
from xen.util.memmap import memmap_parse
|
||||
memmap = memmap_parse(memmap)
|
||||
log.debug("creating vmx domain with cmdline: %s" %(cmdline,))
|
||||
vm.create_domain("vmx", kernel, ramdisk, cmdline, memmap)
|
||||
return vm
|
||||
|
||||
def vm_field_ignore(vm, config, val, index):
|
||||
"""Dummy config field handler used for fields with built-in handling.
|
||||
|
||||
@@ -1197,9 +975,16 @@ def vm_field_maxmem(vm, config, val, index):
|
||||
|
||||
#============================================================================
|
||||
# Register image handlers.
|
||||
add_image_handler('linux', vm_image_linux)
|
||||
add_image_handler('plan9', vm_image_plan9)
|
||||
add_image_handler('vmx', vm_image_vmx)
|
||||
from image import \
|
||||
addImageHandlerClass, \
|
||||
ImageHandler, \
|
||||
LinuxImageHandler, \
|
||||
Plan9ImageHandler, \
|
||||
VmxImageHandler
|
||||
|
||||
addImageHandlerClass(LinuxImageHandler)
|
||||
addImageHandlerClass(Plan9ImageHandler)
|
||||
addImageHandlerClass(VmxImageHandler)
|
||||
|
||||
# Ignore the fields we already handle.
|
||||
add_config_handler('name', vm_field_ignore)
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
import os
|
||||
|
||||
import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
|
||||
from xen.xend import sxp
|
||||
from xen.xend.XendError import VmError
|
||||
from xen.xend.XendLogging import log
|
||||
#from xen.xend.xenstore import DBVar
|
||||
|
||||
class ImageHandler:
|
||||
"""Abstract base class for image handlers.
|
||||
|
||||
initDomain() is called to initialise the domain memory.
|
||||
|
||||
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 if it needs one. The default is to do nothing.
|
||||
|
||||
The method destroy() is called when the domain is destroyed.
|
||||
The default is to do nothing.
|
||||
|
||||
"""
|
||||
|
||||
#======================================================================
|
||||
# Class vars and methods.
|
||||
|
||||
"""Table of image handler classes for virtual machine images.
|
||||
Indexed by image type.
|
||||
"""
|
||||
imageHandlerClasses = {}
|
||||
|
||||
def addImageHandlerClass(cls, h):
|
||||
"""Add a handler class for an image type
|
||||
@param h: handler: ImageHandler subclass
|
||||
"""
|
||||
cls.imageHandlerClasses[h.ostype] = h
|
||||
|
||||
addImageHandlerClass = classmethod(addImageHandlerClass)
|
||||
|
||||
def findImageHandlerClass(cls, image):
|
||||
"""Find the image handler class for an image config.
|
||||
|
||||
@param image config
|
||||
@return ImageHandler subclass or None
|
||||
"""
|
||||
ty = sxp.name(image)
|
||||
if ty is None:
|
||||
raise VmError('missing image type')
|
||||
imageClass = cls.imageHandlerClasses.get(ty)
|
||||
if imageClass is None:
|
||||
raise VmError('unknown image type: ' + ty)
|
||||
return imageClass
|
||||
|
||||
findImageHandlerClass = classmethod(findImageHandlerClass)
|
||||
|
||||
def create(cls, vm, image):
|
||||
"""Create an image handler for a vm.
|
||||
|
||||
@param vm vm
|
||||
@param image image config
|
||||
@return ImageHandler instance
|
||||
"""
|
||||
imageClass = cls.findImageHandlerClass(image)
|
||||
return imageClass(vm, image)
|
||||
|
||||
create = classmethod(create)
|
||||
|
||||
#======================================================================
|
||||
# Instance vars and methods.
|
||||
|
||||
#db = None
|
||||
ostype = None
|
||||
|
||||
config = None
|
||||
kernel = None
|
||||
ramdisk = None
|
||||
cmdline = None
|
||||
flags = 0
|
||||
|
||||
#__exports__ = [
|
||||
# DBVar('ostype', ty='str'),
|
||||
# DBVar('config', ty='sxpr'),
|
||||
# DBVar('kernel', ty='str'),
|
||||
# DBVar('ramdisk', ty='str'),
|
||||
# DBVar('cmdline', ty='str'),
|
||||
# DBVar('flags', ty='int'),
|
||||
# ]
|
||||
|
||||
def __init__(self, vm, config):
|
||||
self.vm = vm
|
||||
#self.db = vm.db.addChild('/image')
|
||||
self.config = config
|
||||
|
||||
#def exportToDB(self, save=False):
|
||||
# self.db.exportToDB(self, fields=self.__exports__, save=save)
|
||||
|
||||
#def importFromDB(self):
|
||||
# self.db.importFromDB(self, fields=self.__exports__)
|
||||
|
||||
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 initDomain(self, dom, memory, cpu, cpu_weight):
|
||||
"""Initial domain create.
|
||||
|
||||
@return domain id
|
||||
"""
|
||||
|
||||
mem_kb = self.getDomainMemory(memory)
|
||||
if not self.vm.restore:
|
||||
dom = xc.domain_create(dom = dom or 0)
|
||||
# if bootloader, unlink here. But should go after buildDomain() ?
|
||||
if self.vm.bootloader:
|
||||
self.unlink(self.kernel)
|
||||
self.unlink(self.ramdisk)
|
||||
if dom <= 0:
|
||||
raise VmError('Creating domain failed: name=%s' % self.vm.name)
|
||||
log.debug("initDomain: cpu=%d mem_kb=%d dom=%d", cpu, mem_kb, dom)
|
||||
# xc.domain_setuuid(dom, uuid)
|
||||
xc.domain_setcpuweight(dom, cpu_weight)
|
||||
xc.domain_setmaxmem(dom, mem_kb)
|
||||
xc.domain_memory_increase_reservation(dom, mem_kb)
|
||||
if cpu != -1:
|
||||
xc.domain_pincpu(dom, 0, 1<<int(cpu))
|
||||
return dom
|
||||
|
||||
def createImage(self):
|
||||
"""Entry point to create domain memory image.
|
||||
Override in subclass if needed.
|
||||
"""
|
||||
self.configure()
|
||||
self.createDomain()
|
||||
|
||||
def configure(self):
|
||||
"""Config actions common to all unix-like domains."""
|
||||
self.kernel = sxp.child_value(self.config, "kernel")
|
||||
self.cmdline = ""
|
||||
ip = sxp.child_value(self.config, "ip", None)
|
||||
if ip:
|
||||
self.cmdline += " ip=" + ip
|
||||
root = sxp.child_value(self.config, "root")
|
||||
if root:
|
||||
self.cmdline += " root=" + root
|
||||
args = sxp.child_value(self.config, "args")
|
||||
if args:
|
||||
self.cmdline += " " + args
|
||||
self.ramdisk = sxp.child_value(self.config, "ramdisk", '')
|
||||
|
||||
def createDomain(self):
|
||||
"""Build the domain boot image.
|
||||
"""
|
||||
# Set params and call buildDomain().
|
||||
self.flags = 0
|
||||
if self.vm.netif_backend: self.flags |= SIF_NET_BE_DOMAIN
|
||||
if self.vm.blkif_backend: self.flags |= SIF_BLK_BE_DOMAIN
|
||||
|
||||
if self.vm.recreate or self.vm.restore:
|
||||
return
|
||||
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) >= 256:
|
||||
log.warning('kernel cmdline too long, domain %d', self.vm.getDomain())
|
||||
|
||||
log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype,
|
||||
self.vm.getDomain(), self.vm.vcpus)
|
||||
err = self.buildDomain()
|
||||
if err != 0:
|
||||
raise VmError('Building domain failed: ostype=%s dom=%d err=%d'
|
||||
% (self.ostype, self.vm.getDomain(), err))
|
||||
|
||||
def getDomainMemory(self, mem_mb):
|
||||
"""Memory (in KB) the domain will need for mem_mb (in MB)."""
|
||||
return mem_mb * 1024
|
||||
|
||||
def buildDomain(self):
|
||||
"""Build the domain. Define in subclass."""
|
||||
raise NotImplementedError()
|
||||
|
||||
def createDeviceModel(self):
|
||||
"""Create device model for the domain (define in subclass if needed)."""
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
"""Extra cleanup on domain destroy (define in subclass if needed)."""
|
||||
pass
|
||||
|
||||
addImageHandlerClass = ImageHandler.addImageHandlerClass
|
||||
|
||||
class LinuxImageHandler(ImageHandler):
|
||||
|
||||
ostype = "linux"
|
||||
|
||||
def buildDomain(self):
|
||||
#if self.vm.store_channel:
|
||||
# store_evtchn = self.vm.store_channel.port2
|
||||
#else:
|
||||
# store_evtchn = 0
|
||||
d = xc.linux_build(dom = self.vm.getDomain(),
|
||||
image = self.kernel,
|
||||
control_evtchn = self.vm.channel.getRemotePort(),
|
||||
#store_evtchn = store_evtchn,
|
||||
cmdline = self.cmdline,
|
||||
ramdisk = self.ramdisk,
|
||||
flags = self.flags,
|
||||
vcpus = self.vm.vcpus)
|
||||
#if isinstance(d, dict):
|
||||
# self.vm.store_mfn = d.get('store_mfn')
|
||||
return 0
|
||||
|
||||
class Plan9ImageHandler(ImageHandler):
|
||||
|
||||
ostype = "plan9"
|
||||
|
||||
def buildDomain(self):
|
||||
return xc.plan9_build(dom = self.vm.getDomain(),
|
||||
image = self.kernel,
|
||||
control_evtchn = self.vm.channel.getRemotePort(),
|
||||
cmdline = self.cmdline,
|
||||
ramdisk = self.ramdisk,
|
||||
flags = self.flags,
|
||||
vcpus = self.vm.vcpus)
|
||||
|
||||
class VmxImageHandler(ImageHandler):
|
||||
|
||||
#__exports__ = ImageHandler.__exports__ + [
|
||||
# DBVar('memmap', ty='str'),
|
||||
# DBVar('memmap_value', ty='sxpr'),
|
||||
# # device channel?
|
||||
# ]
|
||||
|
||||
ostype = "vmx"
|
||||
memmap = None
|
||||
memmap_value = None
|
||||
device_channel = None
|
||||
|
||||
def createImage(self):
|
||||
"""Create a VM for the VMX environment.
|
||||
"""
|
||||
self.configure()
|
||||
self.parseMemmap()
|
||||
self.createDomain()
|
||||
|
||||
def buildDomain(self):
|
||||
return xc.vmx_build(dom = self.vm.getDomain(),
|
||||
image = self.kernel,
|
||||
control_evtchn = 0,
|
||||
memsize = self.vm.memory,
|
||||
memmap = self.memmap_value,
|
||||
cmdline = self.cmdline,
|
||||
ramdisk = self.ramdisk,
|
||||
flags = self.flags)
|
||||
|
||||
def parseMemmap(self):
|
||||
self.memmap = sxp.child_value(self.vm.config, "memmap")
|
||||
if self.memmap is None:
|
||||
raise VmError("missing memmap")
|
||||
memmap = sxp.parse(open(self.memmap))[0]
|
||||
from xen.util.memmap import memmap_parse
|
||||
self.memmap_value = memmap_parse(memmap)
|
||||
|
||||
def createDeviceModel_old(self):
|
||||
device_model = sxp.child_value(self.vm.config, 'device_model')
|
||||
if not device_model:
|
||||
raise VmError("vmx: missing device model")
|
||||
device_config = sxp.child_value(self.vm.config, 'device_config')
|
||||
if not device_config:
|
||||
raise VmError("vmx: missing device config")
|
||||
# Create an event channel.
|
||||
self.device_channel = channel.eventChannel(0, self.vm.getDomain())
|
||||
# Execute device model.
|
||||
#todo: Error handling
|
||||
os.system(device_model
|
||||
+ " -f %s" % device_config
|
||||
+ " -d %d" % self.vm.getDomain()
|
||||
+ " -p %d" % self.device_channel['port1']
|
||||
+ " -m %s" % self.vm.memory)
|
||||
|
||||
def createDeviceModel(self):
|
||||
device_model = sxp.child_value(self.vm.config, 'device_model')
|
||||
if not device_model:
|
||||
raise VmError("vmx: missing device model")
|
||||
device_config = sxp.child_value(self.vm.config, 'device_config')
|
||||
if not device_config:
|
||||
raise VmError("vmx: missing device config")
|
||||
# Create an event channel
|
||||
self.device_channel = channel.eventChannel(0, self.vm.getDomain())
|
||||
# Execute device model.
|
||||
#todo: Error handling
|
||||
# XXX RN: note that the order of args matter!
|
||||
os.system(device_model
|
||||
+ " -f %s" % device_config
|
||||
+ self.vncParams()
|
||||
+ " -d %d" % self.vm.getDomain()
|
||||
+ " -p %d" % self.device_channel['port1']
|
||||
+ " -m %s" % self.vm.memory)
|
||||
|
||||
def vncParams(self):
|
||||
# see if a vncviewer was specified
|
||||
# XXX RN: bit of a hack. should unify this, maybe stick in config space
|
||||
vncconnect=""
|
||||
image = self.config
|
||||
args = sxp.child_value(image, "args")
|
||||
if args:
|
||||
arg_list = string.split(args)
|
||||
for arg in arg_list:
|
||||
al = string.split(arg, '=')
|
||||
if al[0] == "VNC_VIEWER":
|
||||
vncconnect=" -v %s" % al[1]
|
||||
break
|
||||
return vncconnect
|
||||
|
||||
def destroy(self):
|
||||
channel.eventChannelClose(self.device_channel)
|
||||
|
||||
def getDomainMemory(self, mem_mb):
|
||||
return (mem_mb * 1024) + self.getPageTableSize(mem_mb)
|
||||
|
||||
def getPageTableSize(self, mem_mb):
|
||||
"""Return the size of memory needed for 1:1 page tables for physical
|
||||
mode.
|
||||
|
||||
@param mem_mb: size in MB
|
||||
@return size in KB
|
||||
"""
|
||||
# Logic x86-32 specific.
|
||||
# 1 page for the PGD + 1 pte page for 4MB of memory (rounded)
|
||||
return (1 + ((mem_mb + 3) >> 2)) * 4
|
||||