aboutsummaryrefslogtreecommitdiffstats
path: root/tools/python/xen/xend/XendDomain.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/python/xen/xend/XendDomain.py')
-rw-r--r--tools/python/xen/xend/XendDomain.py284
1 files changed, 151 insertions, 133 deletions
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
index 3fb066327f..ff688f6df1 100644
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -7,46 +7,42 @@
"""
import errno
import os
-import scheduler
-import string
import sys
-import traceback
import time
+import traceback
import xen.lowlevel.xc; xc = xen.lowlevel.xc.new()
-from xen.xend.server import relocate
-import sxp
-import XendRoot; xroot = XendRoot.instance()
-import XendCheckpoint
-import XendDB
-import XendDomainInfo
-import EventServer; eserver = EventServer.instance()
-from XendError import XendError
-from XendLogging import log
-
+from xen.xend import sxp
+from xen.xend import XendRoot; xroot = XendRoot.instance()
+from xen.xend import XendCheckpoint
+from xen.xend.XendDomainInfo import XendDomainInfo, shutdown_reason
+from xen.xend import EventServer; eserver = EventServer.instance()
+from xen.xend.XendError import XendError
+from xen.xend.XendLogging import log
+from xen.xend import scheduler
from xen.xend.server import channel
+from xen.xend.server import relocate
+from xen.xend.uuid import getUuid
+from xen.xend.xenstore import XenNode, DBMap
__all__ = [ "XendDomain" ]
SHUTDOWN_TIMEOUT = 30
+class XendDomainDict(dict):
+ def get_by_name(self, name):
+ try:
+ return filter(lambda d: d.name == name, self.values())[0]
+ except IndexError, err:
+ return None
+
class XendDomain:
"""Index of all domains. Singleton.
"""
- """Path to domain database."""
- dbpath = "domain"
-
- class XendDomainDict(dict):
- def get_by_name(self, name):
- try:
- return filter(lambda d: d.name == name, self.values())[0]
- except IndexError, err:
- return None
-
"""Dict of domain info indexed by domain id."""
- domains = XendDomainDict()
+ domains = None
def __init__(self):
# Hack alert. Python does not support mutual imports, but XendDomainInfo
@@ -54,8 +50,8 @@ class XendDomain:
# to import XendDomain from XendDomainInfo causes unbounded recursion.
# So we stuff the XendDomain instance (self) into xroot's components.
xroot.add_component("xen.xend.XendDomain", self)
- # Table of domain info indexed by domain id.
- self.db = XendDB.XendDB(self.dbpath)
+ self.domains = XendDomainDict()
+ self.dbmap = DBMap(db=XenNode("/domain"))
eserver.subscribe('xend.virq', self.onVirq)
self.initial_refresh()
@@ -77,18 +73,16 @@ class XendDomain:
domlist = xc.domain_getinfo()
doms = {}
for d in domlist:
- domid = str(d['dom'])
+ domid = d['dom']
doms[domid] = d
return doms
def xen_domain(self, dom):
"""Get info about a single domain from xc.
Returns None if not found.
+
+ @param dom domain id (int)
"""
- try:
- dom = int(dom)
- except ValueError:
- return None
dominfo = xc.domain_getinfo(dom, 1)
if dominfo == [] or dominfo[0]['dom'] != dom:
dominfo = None
@@ -100,37 +94,36 @@ class XendDomain:
"""Refresh initial domain info from db.
"""
doms = self.xen_domains()
- for config in self.db.fetchall("").values():
- domid = str(sxp.child_value(config, 'id'))
- if domid in doms:
+ self.dbmap.readDB()
+ for domdb in self.dbmap.values():
+ try:
+ domid = int(domdb.id)
+ except:
+ domid = None
+ # XXX if domid in self.domains, then something went wrong
+ if (domid is None) or (domid in self.domains):
+ domdb.delete()
+ elif domid in doms:
try:
- self._new_domain(config, doms[domid])
- self.update_domain(domid)
+ self._new_domain(domdb, doms[domid])
except Exception, ex:
- log.exception("Error recreating domain info: id=%s", domid)
+ log.exception("Error recreating domain info: id=%d", domid)
self._delete_domain(domid)
else:
self._delete_domain(domid)
self.refresh(cleanup=True)
- def sync_domain(self, info):
- """Sync info for a domain to disk.
-
- info domain info
- """
- self.db.save(info.id, info.sxpr())
-
def close(self):
pass
- def _new_domain(self, savedinfo, info):
+ def _new_domain(self, db, info):
"""Create a domain entry from saved info.
- @param savedinfo: saved info from the db
- @param info: domain info from xen
+ @param db: saved info from the db
+ @param info: domain info from xen
@return: domain
"""
- dominfo = XendDomainInfo.vm_recreate(savedinfo, info)
+ dominfo = XendDomainInfo.recreate(db, info)
self.domains[dominfo.id] = dominfo
return dominfo
@@ -144,11 +137,11 @@ class XendDomain:
for i, d in self.domains.items():
if i != d.id:
del self.domains[i]
- self.db.delete(i)
+ self.dbmap.delete(d.uuid)
if info.id in self.domains:
notify = False
self.domains[info.id] = info
- self.sync_domain(info)
+ info.exportToDB(save=True)
if notify:
eserver.inject('xend.domain.create', [info.name, info.id])
@@ -158,12 +151,26 @@ class XendDomain:
@param id: domain id
@param notify: send a domain died event if true
"""
+ try:
+ if self.xen_domain(id):
+ return
+ except:
+ pass
info = self.domains.get(id)
if info:
del self.domains[id]
+ info.cleanup()
+ info.delete()
if notify:
eserver.inject('xend.domain.died', [info.name, info.id])
- self.db.delete(id)
+ # XXX this should not be needed
+ for domdb in self.dbmap.values():
+ try:
+ domid = int(domdb.id)
+ except:
+ domid = None
+ if (domid is None) or (domid == id):
+ domdb.delete()
def reap(self):
"""Look for domains that have crashed or stopped.
@@ -178,22 +185,19 @@ class XendDomain:
not(d['running'] or d['paused'] or d['blocked']))
if dead:
casualties.append(d)
- destroyed = 0
for d in casualties:
- id = str(d['dom'])
- #print 'reap>', id
+ id = d['dom']
dominfo = self.domains.get(id)
name = (dominfo and dominfo.name) or '??'
if dominfo and dominfo.is_terminated():
- #print 'reap> already terminated:', id
continue
- log.debug('XendDomain>reap> domain died name=%s id=%s', name, id)
+ log.debug('XendDomain>reap> domain died name=%s id=%d', name, id)
if d['shutdown']:
- reason = XendDomainInfo.shutdown_reason(d['shutdown_reason'])
- log.debug('XendDomain>reap> shutdown name=%s id=%s reason=%s', name, id, reason)
+ reason = shutdown_reason(d['shutdown_reason'])
+ log.debug('XendDomain>reap> shutdown name=%s id=%d reason=%s', name, id, reason)
if reason in ['suspend']:
if dominfo and dominfo.is_terminated():
- log.debug('XendDomain>reap> Suspended domain died id=%s', id)
+ log.debug('XendDomain>reap> Suspended domain died id=%d', id)
else:
eserver.inject('xend.domain.suspended', [name, id])
if dominfo:
@@ -203,10 +207,9 @@ class XendDomain:
eserver.inject('xend.domain.exit', [name, id, reason])
self.domain_restart_schedule(id, reason)
else:
- if xroot.get_enable_dump() == 'true':
- xc.domain_dumpcore(dom = int(id), corefile = "/var/xen/dump/%s.%s.core"%(name,id))
+ if xroot.get_enable_dump():
+ self.domain_dumpcore(id)
eserver.inject('xend.domain.exit', [name, id, 'crash'])
- destroyed += 1
self.final_domain_destroy(id)
def refresh(self, cleanup=False):
@@ -216,7 +219,7 @@ class XendDomain:
self.reap()
doms = self.xen_domains()
# Add entries for any domains we don't know about.
- for (id, d) in doms.items():
+ for id in doms.keys():
if id not in self.domains:
self.domain_lookup(id)
# Remove entries for domains that no longer exist.
@@ -234,16 +237,7 @@ class XendDomain:
scheduler.now(self.domain_restarts)
def update_domain(self, id):
- """Update the saved info for a domain.
-
- @param id: domain id
- """
- dominfo = self.domains.get(id)
- if dominfo:
- self.sync_domain(dominfo)
-
- def refresh_domain(self, id):
- """Refresh information for a single domain.
+ """Update information for a single domain.
@param id: domain id
"""
@@ -279,8 +273,7 @@ class XendDomain:
@param config: configuration
@return: domain
"""
- dominfo = XendDomainInfo.vm_create(config)
- self._add_domain(dominfo)
+ dominfo = XendDomainInfo.create(self.dbmap, config)
return dominfo
def domain_restart(self, dominfo):
@@ -293,7 +286,6 @@ class XendDomain:
[dominfo.name, dominfo.id, "begin"])
try:
dominfo.restart()
- self._add_domain(dominfo)
log.info('Restarted domain name=%s id=%s', dominfo.name, dominfo.id)
eserver.inject("xend.domain.restart",
[dominfo.name, dominfo.id, "success"])
@@ -309,14 +301,13 @@ class XendDomain:
"""Configure an existing domain. This is intended for internal
use by domain restore and migrate.
- @param id: domain id
@param vmconfig: vm configuration
"""
config = sxp.child_value(vmconfig, 'config')
- dominfo = XendDomainInfo.vm_restore(config)
- self._add_domain(dominfo)
+ uuid = sxp.child_value(vmconfig, 'uuid')
+ dominfo = XendDomainInfo.restore(self.dbmap, config, uuid=uuid)
return dominfo
-
+
def domain_restore(self, src, progress=False):
"""Restore a domain from file.
@@ -326,9 +317,7 @@ class XendDomain:
try:
fd = os.open(src, os.O_RDONLY)
-
return XendCheckpoint.restore(self, fd)
-
except OSError, ex:
raise XendError("can't read guest state file %s: %s" %
(src, ex[1]))
@@ -339,24 +328,35 @@ class XendDomain:
@param id: domain id
@return: domain object (or None)
"""
- id = str(id)
- self.refresh_domain(id)
+ self.update_domain(id)
return self.domains.get(id)
- def domain_lookup(self, name):
- name = str(name)
- dominfo = self.domains.get_by_name(name) or self.domains.get(name)
- if dominfo:
- return dominfo
- try:
- d = self.xen_domain(name)
- if d:
- log.info("Creating entry for unknown domain: id=%s", name)
- dominfo = XendDomainInfo.vm_recreate(None, d)
- self._add_domain(dominfo)
- return dominfo
- except Exception, ex:
- log.exception("Error creating domain info: id=%s", name)
+ def domain_lookup(self, id):
+ dominfo = self.domains.get(id)
+ if not dominfo:
+ try:
+ info = self.xen_domain(id)
+ if info:
+ uuid = getUuid()
+ log.info(
+ "Creating entry for unknown domain: id=%d uuid=%s",
+ id, uuid)
+ db = self.dbmap.addChild(uuid)
+ dominfo = XendDomainInfo.recreate(db, info)
+ self._add_domain(dominfo)
+ except Exception, ex:
+ log.exception("Error creating domain info: id=%d", id)
+ return dominfo
+
+ def domain_lookup_by_name(self, name):
+ dominfo = self.domains.get_by_name(name)
+ if not dominfo:
+ try:
+ id = int(name)
+ dominfo = self.domain_lookup(id)
+ except ValueError:
+ pass
+ return dominfo
def domain_unpause(self, id):
"""Unpause domain execution.
@@ -366,7 +366,7 @@ class XendDomain:
dominfo = self.domain_lookup(id)
eserver.inject('xend.domain.unpause', [dominfo.name, dominfo.id])
try:
- return xc.domain_unpause(dom=dominfo.dom)
+ return xc.domain_unpause(dom=dominfo.id)
except Exception, ex:
raise XendError(str(ex))
@@ -378,7 +378,7 @@ class XendDomain:
dominfo = self.domain_lookup(id)
eserver.inject('xend.domain.pause', [dominfo.name, dominfo.id])
try:
- return xc.domain_pause(dom=dominfo.dom)
+ return xc.domain_pause(dom=dominfo.id)
except Exception, ex:
raise XendError(str(ex))
@@ -436,7 +436,7 @@ class XendDomain:
@param id: domain id
@param reason: shutdown reason
"""
- log.debug('domain_restart_schedule> %s %s %d', id, reason, force)
+ log.debug('domain_restart_schedule> %d %s %d', id, reason, force)
dominfo = self.domain_lookup(id)
if not dominfo:
return
@@ -484,7 +484,7 @@ class XendDomain:
except:
#todo
try:
- val = xc.domain_destroy(dom=int(id))
+ val = xc.domain_destroy(dom=id)
except Exception, ex:
raise XendError(str(ex))
return val
@@ -553,7 +553,7 @@ class XendDomain:
"""
dominfo = self.domain_lookup(id)
try:
- return xc.domain_pincpu(int(dominfo.id), vcpu, cpumap)
+ return xc.domain_pincpu(dominfo.id, vcpu, cpumap)
except Exception, ex:
raise XendError(str(ex))
@@ -562,7 +562,7 @@ class XendDomain:
"""
dominfo = self.domain_lookup(id)
try:
- return xc.bvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv,
+ return xc.bvtsched_domain_set(dom=dominfo.id, mcuadv=mcuadv,
warpback=warpback, warpvalue=warpvalue,
warpl=warpl, warpu=warpu)
except Exception, ex:
@@ -573,7 +573,7 @@ class XendDomain:
"""
dominfo = self.domain_lookup(id)
try:
- return xc.bvtsched_domain_get(dominfo.dom)
+ return xc.bvtsched_domain_get(dominfo.id)
except Exception, ex:
raise XendError(str(ex))
@@ -581,20 +581,21 @@ class XendDomain:
def domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight):
"""Set Simple EDF scheduler parameters for a domain.
"""
- dominfo = self.domain_lookup(id)
+ dominfo = self.domain_lookup(id)
try:
- return xc.sedf_domain_set(dominfo.dom, period, slice, latency, extratime, weight)
+ return xc.sedf_domain_set(dominfo.id, period, slice, latency, extratime, weight)
except Exception, ex:
raise XendError(str(ex))
def domain_cpu_sedf_get(self, id):
- """Get Atropos scheduler parameters for a domain.
+ """Get Simple EDF scheduler parameters for a domain.
"""
dominfo = self.domain_lookup(id)
try:
- return xc.sedf_domain_get(dominfo.dom)
+ return xc.sedf_domain_get(dominfo.id)
except Exception, ex:
raise XendError(str(ex))
+
def domain_device_create(self, id, devconfig):
"""Create a new device for a domain.
@@ -603,44 +604,44 @@ class XendDomain:
"""
dominfo = self.domain_lookup(id)
val = dominfo.device_create(devconfig)
- self.update_domain(dominfo.id)
+ dominfo.exportToDB()
return val
- def domain_device_configure(self, id, devconfig, idx):
+ def domain_device_configure(self, id, devconfig, devid):
"""Configure an existing device for a domain.
@param id: domain id
@param devconfig: device configuration
- @param idx: device index
+ @param devid: device id
@return: updated device configuration
"""
dominfo = self.domain_lookup(id)
- val = dominfo.device_configure(devconfig, idx)
- self.update_domain(dominfo.id)
+ val = dominfo.device_configure(devconfig, devid)
+ dominfo.exportToDB()
return val
- def domain_device_refresh(self, id, type, idx):
+ def domain_device_refresh(self, id, type, devid):
"""Refresh a device.
@param id: domain id
- @param idx: device index
+ @param devid: device id
@param type: device type
"""
dominfo = self.domain_lookup(id)
- val = dominfo.device_refresh(type, idx)
- self.update_domain(dominfo.id)
+ val = dominfo.device_refresh(type, devid)
+ dominfo.exportToDB()
return val
- def domain_device_destroy(self, id, type, idx):
+ def domain_device_destroy(self, id, type, devid):
"""Destroy a device.
@param id: domain id
- @param idx: device index
+ @param devid: device id
@param type: device type
"""
dominfo = self.domain_lookup(id)
- val = dominfo.device_destroy(type, idx)
- self.update_domain(dominfo.id)
+ val = dominfo.device_destroy(type, devid)
+ dominfo.exportToDB()
return val
def domain_devtype_ls(self, id, type):
@@ -653,22 +654,22 @@ class XendDomain:
dominfo = self.domain_lookup(id)
return dominfo.getDeviceSxprs(type)
- def domain_devtype_get(self, id, type, idx):
+ def domain_devtype_get(self, id, type, devid):
"""Get a device from a domain.
-
+
@param id: domain
@param type: device type
- @param idx: device index
+ @param devid: device id
@return: device object (or None)
"""
dominfo = self.domain_lookup(id)
- return dominfo.getDeviceByIndex(type, idx)
+ return dominfo.getDevice(type, devid)
def domain_vif_limit_set(self, id, vif, credit, period):
"""Limit the vif's transmission rate
"""
dominfo = self.domain_lookup(id)
- dev = dominfo.getDeviceById('vif', vif)
+ dev = dominfo.getDevice('vif', vif)
if not dev:
raise XendError("invalid vif")
return dev.setCreditLimit(credit, period)
@@ -681,30 +682,47 @@ class XendDomain:
"""
dominfo = self.domain_lookup(id)
try:
- return xc.shadow_control(dominfo.dom, op)
+ return xc.shadow_control(dominfo.id, op)
except Exception, ex:
raise XendError(str(ex))
def domain_maxmem_set(self, id, mem):
"""Set the memory limit for a domain.
- @param dom: domain
+ @param id: domain
@param mem: memory limit (in MB)
@return: 0 on success, -1 on error
"""
dominfo = self.domain_lookup(id)
maxmem = int(mem) * 1024
try:
- return xc.domain_setmaxmem(dominfo.dom, maxmem_kb = maxmem)
+ return xc.domain_setmaxmem(dominfo.id, maxmem_kb = maxmem)
except Exception, ex:
raise XendError(str(ex))
- def domain_mem_target_set(self, id, target):
+ def domain_mem_target_set(self, id, mem):
+ """Set the memory target for a domain.
+
+ @param id: domain
+ @param mem: memory target (in MB)
+ @return: 0 on success, -1 on error
+ """
dominfo = self.domain_lookup(id)
- return dominfo.mem_target_set(target)
-
+ return dominfo.mem_target_set(mem)
+ def domain_dumpcore(self, id):
+ """Save a core dump for a crashed domain.
+ @param id: domain
+ """
+ dominfo = self.domain_lookup(id)
+ corefile = "/var/xen/dump/%s.%s.core"% (dominfo.name, dominfo.id)
+ try:
+ xc.domain_dumpcore(dom=dominfo.id, corefile=corefile)
+ except Exception, ex:
+ log.warning("Dumpcore failed, id=%s name=%s: %s",
+ dominfo.id, dominfo.name, ex)
+
def instance():
"""Singleton constructor. Use this instead of the class constructor.
"""