aboutsummaryrefslogtreecommitdiffstats
path: root/tools/python/xen/xend/XendDomainInfo.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/python/xen/xend/XendDomainInfo.py')
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py704
1 files changed, 256 insertions, 448 deletions
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 0dc1aae79c..16415d78a7 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -14,21 +14,23 @@ import time
import threading
import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
-import xen.util.ip
-from xen.xend.server import channel, controller
+from xen.util.ip import check_subnet, get_current_ipgw
from xen.util.blkif import blkdev_uname_to_file
-from server.channel import channelFactory
-import server.SrvDaemon; xend = server.SrvDaemon.instance()
-from server import messages
+from xen.xend.server import controller
+from xen.xend.server import SrvDaemon; xend = SrvDaemon.instance()
+from xen.xend.server import messages
+from xen.xend.server.channel import EventChannel, channelFactory
+from xen.xend import sxp
+from xen.xend.PrettyPrint import prettyprintstring
from xen.xend.XendBootloader import bootloader
-import sxp
-from XendLogging import log
+from xen.xend.XendLogging import log
from XendError import XendError, VmError
-from XendRoot import get_component
+from xen.xend.XendRoot import get_component
-from PrettyPrint import prettyprintstring
+from xen.xend.uuid import getUuid
+from xen.xend.xenstore import DBVar
"""Flag for a block device backend domain."""
SIF_BLK_BE_DOMAIN = (1<<4)
@@ -45,11 +47,16 @@ DOMAIN_REBOOT = 1
"""Shutdown code for suspend."""
DOMAIN_SUSPEND = 2
+"""Shutdown code for crash."""
+DOMAIN_CRASH = 3
+
"""Map shutdown codes to strings."""
shutdown_reasons = {
DOMAIN_POWEROFF: "poweroff",
DOMAIN_REBOOT : "reboot",
- DOMAIN_SUSPEND : "suspend" }
+ DOMAIN_SUSPEND : "suspend",
+ DOMAIN_CRASH : "crash",
+ }
"""Map shutdown reasons to the message type to use.
"""
@@ -81,7 +88,7 @@ STATE_VM_SUSPENDED = "suspended"
def domain_exists(name):
# See comment in XendDomain constructor.
xd = get_component('xen.xend.XendDomain')
- return xd.domain_lookup(name)
+ return xd.domain_lookup_by_name(name)
def shutdown_reason(code):
"""Get a shutdown reason from a code.
@@ -110,25 +117,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.
"""
@@ -139,61 +127,6 @@ def add_device_handler(name, type):
def get_device_handler(name):
return device_handlers[name]
-
-
-def vm_create(config):
- """Create a VM from a configuration.
- If a vm has been partially created and there is an error it
- is destroyed.
-
- @param config configuration
- @raise: VmError for invalid configuration
- """
- vm = XendDomainInfo()
- vm.construct(config)
- return vm
-
-def vm_restore(config):
- """Create a domain and a VM object to do a restore.
-
- @param config: domain configuration
- """
- vm = XendDomainInfo()
- dom = xc.domain_create()
- vm.dom_construct(dom, config)
- return vm
-
-def vm_recreate(savedinfo, info):
- """Create the VM object for an existing domain.
-
- @param savedinfo: saved info from the domain DB
- @type savedinfo: sxpr
- @param info: domain info from xc
- @type info: xc domain dict
- """
- log.debug('savedinfo=' + prettyprintstring(savedinfo))
- log.debug('info=' + str(info))
- vm = XendDomainInfo()
- vm.recreate = True
- vm.savedinfo = savedinfo
- vm.setdom(info['dom'])
- vm.memory = info['mem_kb']/1024
- start_time = sxp.child_value(savedinfo, 'start_time')
- if start_time is not None:
- vm.start_time = float(start_time)
- vm.restart_state = sxp.child_value(savedinfo, 'restart_state')
- vm.restart_count = int(sxp.child_value(savedinfo, 'restart_count', 0))
- restart_time = sxp.child_value(savedinfo, 'restart_time')
- if restart_time is not None:
- vm.restart_time = float(restart_time)
- config = sxp.child_value(savedinfo, 'config')
- if config:
- vm.construct(config)
- else:
- vm.name = sxp.child_value(savedinfo, 'name', "Domain-%d" % info['dom'])
- vm.recreate = False
- vm.savedinfo = None
- return vm
def dom_get(dom):
"""Get info from xen for an existing domain.
@@ -213,25 +146,104 @@ class XendDomainInfo:
"""
MINIMUM_RESTART_TIME = 20
- def __init__(self):
+ def create(cls, parentdb, config):
+ """Create a VM from a configuration.
+
+ @param parentdb: parent db
+ @param config configuration
+ @raise: VmError for invalid configuration
+ """
+ uuid = getUuid()
+ db = parentdb.addChild(uuid)
+ vm = cls(db)
+ vm.construct(config)
+ vm.saveDB(sync=True)
+ return vm
+
+ create = classmethod(create)
+
+ def recreate(cls, db, info):
+ """Create the VM object for an existing domain.
+
+ @param db: domain db
+ @param info: domain info from xc
+ """
+ dom = info['dom']
+ vm = cls(db)
+ db.readDB()
+ vm.importFromDB()
+ config = vm.config
+ log.debug('info=' + str(info))
+ log.debug('config=' + prettyprintstring(config))
+
+ vm.setdom(dom)
+ vm.memory = info['mem_kb']/1024
+
+ if config:
+ try:
+ vm.recreate = True
+ vm.construct(config)
+ finally:
+ vm.recreate = False
+ else:
+ vm.setName("Domain-%d" % dom)
+
+ vm.exportToDB(save=True)
+ return vm
+
+ recreate = classmethod(recreate)
+
+ def restore(cls, parentdb, config, uuid=None):
+ """Create a domain and a VM object to do a restore.
+
+ @param parentdb: parent db
+ @param config: domain configuration
+ @param uuid: uuid to use
+ """
+ db = parentdb.addChild(uuid)
+ vm = cls(db)
+ dom = xc.domain_create()
+ vm.setdom(dom)
+ vm.dom_construct(vm.id, config)
+ vm.saveDB(sync=True)
+ return vm
+
+ restore = classmethod(restore)
+
+ __exports__ = [
+ DBVar('id', ty='str'),
+ DBVar('name', ty='str'),
+ DBVar('uuid', ty='str'),
+ DBVar('config', ty='sxpr'),
+ DBVar('start_time', ty='float'),
+ DBVar('state', ty='str'),
+ DBVar('store_mfn', ty='long'),
+ DBVar('restart_mode', ty='str'),
+ DBVar('restart_state', ty='str'),
+ DBVar('restart_time', ty='float'),
+ DBVar('restart_count', ty='int'),
+ ]
+
+ def __init__(self, db):
+ self.db = db
+ self.uuid = db.getName()
+
self.recreate = 0
self.restore = 0
+
self.config = None
self.id = None
- self.dom = None
self.cpu_weight = 1
self.start_time = None
self.name = None
self.memory = None
self.image = None
- self.ramdisk = None
- self.cmdline = None
self.channel = None
+ self.store_channel = None
+ self.store_mfn = None
self.controllers = {}
- self.configs = []
-
self.info = None
self.blkif_backend = False
self.netif_backend = False
@@ -249,22 +261,39 @@ class XendDomainInfo:
self.restart_count = 0
self.console_port = None
- self.savedinfo = None
- self.image_handler = None
- self.is_vmx = False
self.vcpus = 1
self.bootloader = None
+ def setDB(self, db):
+ self.db = db
+
+ def saveDB(self, save=False, sync=False):
+ self.db.saveDB(save=save, sync=sync)
+
+ def exportToDB(self, save=False, sync=False):
+ if self.channel:
+ self.channel.saveToDB(self.db.addChild("channel"))
+ if self.store_channel:
+ self.store_channel.saveToDB(self.db.addChild("store_channel"))
+ self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
+
+ def importFromDB(self):
+ self.db.importFromDB(self, fields=self.__exports__)
+
def setdom(self, dom):
"""Set the domain id.
@param dom: domain id
"""
- self.dom = int(dom)
- self.id = str(dom)
+ self.id = int(dom)
+ #self.db.id = self.id
def getDomain(self):
- return self.dom
+ return self.id
+
+ def setName(self, name):
+ self.name = name
+ self.db.name = self.name
def getName(self):
return self.name
@@ -272,6 +301,9 @@ class XendDomainInfo:
def getChannel(self):
return self.channel
+ def getStoreChannel(self):
+ return self.store_channel
+
def update(self, info):
"""Update with info from xc.domain_getinfo().
"""
@@ -284,6 +316,7 @@ class XendDomainInfo:
self.state = state
self.state_updated.notifyAll()
self.state_updated.release()
+ self.saveDB()
def state_wait(self, state):
self.state_updated.acquire()
@@ -293,14 +326,12 @@ class XendDomainInfo:
def __str__(self):
s = "domain"
- s += " id=" + self.id
+ s += " id=" + str(self.id)
s += " name=" + self.name
s += " memory=" + str(self.memory)
console = self.getConsole()
if console:
s += " console=" + str(console.console_port)
- if self.image:
- s += " image=" + self.image
s += ""
return s
@@ -327,9 +358,10 @@ class XendDomainInfo:
self.controllers[type] = ctrl
return ctrl
- def createDevice(self, type, devconfig, recreate=False):
+ def createDevice(self, type, devconfig, change=False):
ctrl = self.findDeviceController(type)
- return ctrl.createDevice(devconfig, recreate=self.recreate)
+ return ctrl.createDevice(devconfig, recreate=self.recreate,
+ change=change)
def configureDevice(self, type, id, devconfig):
ctrl = self.getDeviceController(type)
@@ -343,30 +375,14 @@ class XendDomainInfo:
ctrl = self.getDeviceController(type)
return ctrl.deleteDevice(id)
- def getDevice(self, type, id):
+ def getDevice(self, type, id, error=True):
ctrl = self.getDeviceController(type)
- return ctrl.getDevice(id)
+ return ctrl.getDevice(id, error=error)
- def getDeviceByIndex(self, type, idx):
- ctrl = self.getDeviceController(type)
- return ctrl.getDeviceByIndex(idx)
-
- def getDeviceConfig(self, type, id):
- ctrl = self.getDeviceController(type)
- return ctrl.getDeviceConfig(id)
-
def getDeviceIds(self, type):
ctrl = self.getDeviceController(type)
return ctrl.getDeviceIds()
- def getDeviceIndexes(self, type):
- ctrl = self.getDeviceController(type)
- return ctrl.getDeviceIndexes()
-
- def getDeviceConfigs(self, type):
- ctrl = self.getDeviceController(type)
- return ctrl.getDeviceConfigs()
-
def getDeviceSxprs(self, type):
ctrl = self.getDeviceController(type)
return ctrl.getDeviceSxprs()
@@ -376,7 +392,8 @@ class XendDomainInfo:
['id', self.id],
['name', self.name],
['memory', self.memory] ]
-
+ if self.uuid:
+ sxpr.append(['uuid', self.uuid])
if self.info:
sxpr.append(['maxmem', self.info['maxmem_kb']/1024 ])
run = (self.info['running'] and 'r') or '-'
@@ -403,6 +420,8 @@ class XendDomainInfo:
if self.channel:
sxpr.append(self.channel.sxpr())
+ if self.store_channel:
+ sxpr.append(self.store_channel.sxpr())
console = self.getConsole()
if console:
sxpr.append(console.sxpr())
@@ -454,7 +473,7 @@ class XendDomainInfo:
return
if dominfo.is_terminated():
return
- if not self.dom or (dominfo.dom != self.dom):
+ if not self.id or (dominfo.id != self.id):
raise VmError('vm name clash: ' + name)
def construct(self, config):
@@ -467,10 +486,10 @@ class XendDomainInfo:
self.config = config
try:
# Initial domain create.
- self.name = sxp.child_value(config, 'name')
+ 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()
@@ -481,6 +500,7 @@ class XendDomainInfo:
self.configure_restart()
self.construct_image()
self.configure()
+ self.exportToDB()
except Exception, ex:
# Catch errors, cleanup and re-raise.
print 'Domain construction error:', ex
@@ -492,6 +512,7 @@ class XendDomainInfo:
def register_domain(self):
xd = get_component('xen.xend.XendDomain')
xd._add_domain(self)
+ self.exportToDB()
def configure_cpus(self, config):
try:
@@ -502,8 +523,8 @@ class XendDomainInfo:
if self.memory is None:
raise VmError('missing memory size')
cpu = sxp.child_value(config, 'cpu')
- if self.recreate and self.dom and cpu is not None and int(cpu) >= 0:
- xc.domain_pincpu(self.dom, 0, 1<<int(cpu))
+ if self.recreate and self.id and cpu is not None and int(cpu) >= 0:
+ xc.domain_pincpu(self.id, 0, 1<<int(cpu))
try:
image = sxp.child_value(self.config, 'image')
vcpus = sxp.child_value(image, 'vcpus')
@@ -512,89 +533,50 @@ 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
-
- def config_devices(self, name):
- """Get a list of the 'device' nodes of a given type from the config.
-
- @param name: device type
- @type name: string
- @return: device configs
- @rtype: list
- """
- devices = []
- for d in sxp.children(self.config, 'device'):
- dev = sxp.child0(d)
- if dev is None: continue
- if name == sxp.name(dev):
- devices.append(dev)
- return devices
-
- def get_device_savedinfo(self, type, index):
- val = None
- if self.savedinfo is None:
- return val
- devices = sxp.child(self.savedinfo, 'devices')
- if devices is None:
- return val
- index = str(index)
- for d in sxp.children(devices, type):
- dindex = sxp.child_value(d, 'index')
- if dindex is None: continue
- if str(dindex) == index:
- val = d
- break
- return val
-
- def get_device_recreate(self, type, index):
- return self.get_device_savedinfo(type, index) or self.recreate
-
- def add_config(self, val):
- """Add configuration data to a virtual machine.
-
- @param val: data to add
+ """Construct the boot image for the domain.
"""
- self.configs.append(val)
-
- def destroy(self):
- """Completely destroy the vm.
+ 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 delete(self):
+ """Delete the vm's db.
"""
- self.cleanup()
- return self.destroy_domain()
+ if self.dom_get(self.id):
+ return
+ self.id = None
+ self.saveDB(sync=True)
+ try:
+ # Todo: eventually will have to wait for devices to signal
+ # destruction before can delete the db.
+ if self.db:
+ self.db.delete()
+ except Exception, ex:
+ log.warning("error in domain db delete: %s", ex)
+ pass
def destroy_domain(self):
"""Destroy the vm's domain.
The domain will not finally go away unless all vm
devices have been released.
"""
- if self.channel:
- self.channel.close()
- self.channel = None
- if self.dom is None: return 0
+ if self.id is None:
+ return
try:
- return xc.domain_destroy(dom=self.dom)
+ xc.domain_destroy(dom=self.id)
except Exception, err:
log.exception("Domain destroy failed: %s", self.name)
@@ -603,6 +585,37 @@ class XendDomainInfo:
"""
self.state = STATE_VM_TERMINATED
self.release_devices()
+ if self.channel:
+ try:
+ self.channel.close()
+ self.channel = None
+ except:
+ pass
+ if self.store_channel:
+ try:
+ self.store_channel.close()
+ self.store_channel = None
+ except:
+ pass
+ #try:
+ # self.db.releaseDomain(self.id)
+ #except Exception, ex:
+ # log.warning("error in domain release on xenstore: %s", ex)
+ # pass
+ if self.image:
+ try:
+ self.image.destroy()
+ self.image = None
+ except:
+ pass
+
+ def destroy(self):
+ """Clenup vm and destroy domain.
+ """
+ self.cleanup()
+ self.destroy_domain()
+ self.saveDB()
+ return 0
def is_terminated(self):
"""Check if a domain has been terminated.
@@ -616,20 +629,13 @@ class XendDomainInfo:
for ctrl in self.getDeviceControllers():
if ctrl.isDestroyed(): continue
ctrl.destroyController(reboot=reboot)
- if not reboot:
- self.configs = []
def show(self):
"""Print virtual machine info.
"""
- print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
+ print "[VM dom=%d name=%s memory=%d" % (self.id, self.name, self.memory)
print "image:"
sxp.show(self.image)
- print
- for val in self.configs:
- print "config:"
- sxp.show(val)
- print
print "]"
def init_domain(self):
@@ -639,107 +645,42 @@ class XendDomainInfo:
return
if self.start_time is None:
self.start_time = time.time()
- if self.restore:
- return
- dom = self.dom or 0
- memory = self.memory
try:
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.dom)
- dom = self.dom
- 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.
+ 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)
- @param ostype: OS type
- @param kernel: kernel image
- @param ramdisk: kernel ramdisk
- @param cmdline: kernel commandline
+ def openChannel(self, key, local, remote):
+ """Create a channel to the domain.
+ If saved info is available recreate the channel.
+
+ @param key db key for the saved data (if any)
+ @param local default local port
+ @param remote default remote port
"""
-
- self.create_channel()
- self.build_domain(ostype, kernel, ramdisk, cmdline, memmap)
- self.image = kernel
- self.ramdisk = ramdisk
- self.cmdline = cmdline
-
+ db = self.db.addChild(key)
+ chan = channelFactory().restoreFromDB(db, self.id, local, remote)
+ #todo: save here?
+ #chan.saveToDB(db)
+ return chan
+
+ def eventChannel(self, key):
+ db = self.db.addChild(key)
+ return EventChannel.restoreFromDB(db, 0, self.id)
+
def create_channel(self):
- """Create the control channel to the domain.
- If saved info is available recreate the channel using the saved ports.
+ """Create the channels to the domain.
"""
- local = 0
- remote = 1
- if self.savedinfo:
- info = sxp.child(self.savedinfo, "channel")
- if info:
- local = int(sxp.child_value(info, "local_port", 0))
- remote = int(sxp.child_value(info, "remote_port", 1))
- self.channel = channelFactory().openChannel(self.dom,
- local_port=local,
- remote_port=remote)
+ self.channel = self.openChannel("channel", 0, 1)
+ self.store_channel = self.eventChannel("store_channel")
def create_configured_devices(self):
devices = sxp.children(self.config, 'device')
- indexes = {}
for d in devices:
dev_config = sxp.child0(d)
if dev_config is None:
@@ -748,13 +689,7 @@ class XendDomainInfo:
ctrl_type = get_device_handler(dev_type)
if ctrl_type is None:
raise VmError('unknown device type: ' + dev_type)
- # Keep track of device indexes by type, so we can fish
- # out saved info for recreation.
- idx = indexes.get(dev_type, -1)
- idx += 1
- indexes[ctrl_type] = idx
- recreate = self.get_device_recreate(dev_type, idx)
- self.createDevice(ctrl_type, dev_config, recreate=recreate)
+ self.createDevice(ctrl_type, dev_config)
def create_devices(self):
"""Create the devices for a vm.
@@ -766,43 +701,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.dom)
- # 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.dom
- + " -p %d" % device_channel['port1']
- + " -m %s" % memory)
def device_create(self, dev_config):
"""Create a new device.
@@ -814,16 +712,14 @@ class XendDomainInfo:
self.config.append(['device', dev.getConfig()])
return dev.sxpr()
- def device_configure(self, dev_config, idx):
+ def device_configure(self, dev_config, id):
"""Configure an existing device.
@param dev_config: device configuration
- @param idx: device index
+ @param id: device id
"""
type = sxp.name(dev_config)
- dev = self.getDeviceByIndex(type, idx)
- if not dev:
- raise VmError('invalid device: %s %s' % (type, idx))
+ dev = self.getDevice(type, id)
old_config = dev.getConfig()
new_config = dev.configure(dev_config, change=True)
# Patch new config into vm config.
@@ -833,26 +729,22 @@ class XendDomainInfo:
self.config[old_index] = new_full_config
return new_config
- def device_refresh(self, type, idx):
+ def device_refresh(self, type, id):
"""Refresh a device.
@param type: device type
- @param idx: device index
+ @param id: device id
"""
- dev = self.getDeviceByIndex(type, idx)
- if not dev:
- raise VmError('invalid device: %s %s' % (type, idx))
+ dev = self.getDevice(type, id)
dev.refresh()
- def device_delete(self, type, idx):
+ def device_delete(self, type, id):
"""Destroy and remove a device.
@param type: device type
- @param idx: device index
+ @param id: device id
"""
- dev = self.getDeviceByIndex(type, idx)
- if not dev:
- raise VmError('invalid device: %s %s' % (type, idx))
+ dev = self.getDevice(type, id)
dev_config = dev.getConfig()
if dev_config:
self.config.remove(['device', dev_config])
@@ -861,9 +753,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.
@@ -946,6 +836,7 @@ class XendDomainInfo:
if self.bootloader:
self.config = self.bootloader_config()
self.construct(self.config)
+ self.saveDB()
finally:
self.restart_state = None
@@ -1051,19 +942,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.
"""
@@ -1090,83 +968,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.
@@ -1192,13 +993,20 @@ def vm_field_maxmem(vm, config, val, index):
maxmem = int(maxmem)
except:
raise VmError("invalid maxmem: " + str(maxmem))
- xc.domain_setmaxmem(vm.dom, maxmem_kb = maxmem * 1024)
+ xc.domain_setmaxmem(vm.id, maxmem_kb = maxmem * 1024)
#============================================================================
# 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)