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:
cl349@firebug.cl.cam.ac.uk committed 2005-06-06 16:09:57 +00:00
1 parent 12f5438d72
commit d5affeab6a
3 files changed
+376 -252

No files matched your search

+37 -252
View File
@@ -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)
+338
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.