aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xenmgr/lib/XendDomain.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/xenmgr/lib/XendDomain.py')
-rw-r--r--tools/xenmgr/lib/XendDomain.py347
1 files changed, 347 insertions, 0 deletions
diff --git a/tools/xenmgr/lib/XendDomain.py b/tools/xenmgr/lib/XendDomain.py
new file mode 100644
index 0000000000..60e207da65
--- /dev/null
+++ b/tools/xenmgr/lib/XendDomain.py
@@ -0,0 +1,347 @@
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+"""Handler for domain operations.
+ Nothing here is persistent (across reboots).
+ Needs to be persistent for one uptime.
+"""
+import sys
+
+import Xc; xc = Xc.new()
+import xenctl.ip
+import xenctl.vdisk
+
+import sxp
+import XendRoot
+xroot = XendRoot.instance()
+import XendDB
+import XendDomainInfo
+import XendConsole
+import EventServer
+
+eserver = EventServer.instance()
+
+__all__ = [ "XendDomain" ]
+
+class XendDomain:
+ """Index of all domains. Singleton.
+ """
+
+ dbpath = "domain"
+ domain = {}
+
+ def __init__(self):
+ self.xconsole = XendConsole.instance()
+ # Table of domain info indexed by domain id.
+ self.db = XendDB.XendDB(self.dbpath)
+ #self.domain = {}
+ self.domain_db = self.db.fetchall("")
+ if xroot.get_rebooted():
+ print 'XendDomain> rebooted: removing all domain info'
+ self.rm_all()
+ self.initial_refresh()
+
+ def rm_all(self):
+ """Remove all domain info. Used after reboot.
+ """
+ for (k, v) in self.domain_db.items():
+ self._delete_domain(k, notify=0)
+
+ def initial_refresh(self):
+ """Refresh initial domain info from domain_db.
+ """
+ domlist = xc.domain_getinfo()
+ doms = {}
+ for d in domlist:
+ domid = str(d['dom'])
+ doms[domid] = d
+ for config in self.domain_db.values():
+ domid = int(sxp.child_value(config, 'id'))
+ if domid in doms:
+ self._new_domain(config)
+ else:
+ self._delete_domain(domid)
+ self.refresh()
+
+ def sync(self):
+ """Sync domain db to disk.
+ """
+ self.db.saveall("", self.domain_db)
+
+ def sync_domain(self, dom):
+ """Sync info for a domain to disk.
+
+ dom domain id (string)
+ """
+ self.db.save(dom, self.domain_db[dom])
+
+ def close(self):
+ pass
+
+ def _new_domain(self, info):
+ """Create a domain entry from saved info.
+ """
+ console = None
+ kernel = None
+ id = sxp.child_value(info, 'id')
+ dom = int(id)
+ name = sxp.child_value(info, 'name')
+ memory = int(sxp.child_value(info, 'memory'))
+ consoleinfo = sxp.child(info, 'console')
+ if consoleinfo:
+ consoleid = sxp.child_value(consoleinfo, 'id')
+ console = self.xconsole.console_get(consoleid)
+ if dom and console is None:
+ # Try to connect a console.
+ console = self.xconsole.console_create(dom)
+ config = sxp.child(info, 'config')
+ if config:
+ image = sxp.child(info, 'image')
+ if image:
+ image = sxp.child0(image)
+ kernel = sxp.child_value(image, 'kernel')
+ dominfo = XendDomainInfo.XendDomainInfo(
+ config, dom, name, memory, kernel, console)
+ self.domain[id] = dominfo
+
+ def _add_domain(self, id, info, notify=1):
+ self.domain[id] = info
+ self.domain_db[id] = info.sxpr()
+ self.sync_domain(id)
+ if notify: eserver.inject('xend.domain.created', id)
+
+ def _delete_domain(self, id, notify=1):
+ if id in self.domain:
+ if notify: eserver.inject('xend.domain.died', id)
+ del self.domain[id]
+ if id in self.domain_db:
+ del self.domain_db[id]
+ self.db.delete(id)
+
+ def refresh(self):
+ """Refresh domain list from Xen.
+ """
+ domlist = xc.domain_getinfo()
+ # Index the domlist by id.
+ # Add entries for any domains we don't know about.
+ doms = {}
+ for d in domlist:
+ id = str(d['dom'])
+ doms[id] = d
+ if id not in self.domain:
+ config = None
+ image = None
+ newinfo = XendDomainInfo.XendDomainInfo(
+ config, d['dom'], d['name'], d['mem_kb']/1024, image)
+ self._add_domain(id, newinfo)
+ # Remove entries for domains that no longer exist.
+ for d in self.domain.values():
+ dominfo = doms.get(d.id)
+ if dominfo:
+ d.update(dominfo)
+ else:
+ self._delete_domain(d.id)
+
+ def refresh_domain(self, id):
+ dom = int(id)
+ dominfo = xc.domain_getinfo(dom, 1)
+ if dominfo == [] or dominfo[0]['dom'] != dom:
+ try:
+ self._delete_domain(id)
+ except:
+ pass
+ else:
+ d = self.domain.get(id)
+ if d:
+ d.update(dominfo)
+
+ def domain_ls(self):
+ # List domains.
+ # Update info from kernel first.
+ self.refresh()
+ return self.domain.keys()
+
+ def domains(self):
+ self.refresh()
+ return self.domain.values()
+
+ def domain_create(self, config):
+ # Create domain, log it.
+ deferred = XendDomainInfo.vm_create(config)
+ def fn(dominfo):
+ self._add_domain(dominfo.id, dominfo)
+ return dominfo
+ deferred.addCallback(fn)
+ return deferred
+
+ def domain_get(self, id):
+ id = str(id)
+ self.refresh_domain(id)
+ return self.domain[id]
+
+ def domain_start(self, id):
+ """Start domain running.
+ """
+ dom = int(id)
+ eserver.inject('xend.domain.start', id)
+ return xc.domain_start(dom=dom)
+
+ def domain_stop(self, id):
+ """Stop domain running.
+ """
+ dom = int(id)
+ return xc.domain_stop(dom=dom)
+
+ def domain_shutdown(self, id):
+ """Shutdown domain (nicely).
+ """
+ dom = int(id)
+ if dom <= 0:
+ return 0
+ eserver.inject('xend.domain.shutdown', id)
+ val = xc.domain_destroy(dom=dom, force=0)
+ self.refresh()
+ return val
+
+ def domain_halt(self, id):
+ """Shutdown domain immediately.
+ """
+ dom = int(id)
+ if dom <= 0:
+ return 0
+ eserver.inject('xend.domain.halt', id)
+ val = xc.domain_destroy(dom=dom, force=1)
+ self.refresh()
+ return val
+
+ def domain_migrate(self, id, dst):
+ """Start domain migration.
+ """
+ # Need a cancel too?
+ pass
+
+ def domain_save(self, id, dst, progress=0):
+ """Save domain state to file, halt domain.
+ """
+ dom = int(id)
+ self.domain_stop(id)
+ eserver.inject('xend.domain.save', id)
+ rc = xc.linux_save(dom=dom, state_file=dst, progress=progress)
+ if rc == 0:
+ self.domain_halt(id)
+ return rc
+
+ def domain_restore(self, src, config, progress=0):
+ """Restore domain from file.
+ """
+ dominfo = XendDomainInfo.dom_restore(dom, config)
+ self._add_domain(dominfo.id, dominfo)
+ return dominfo
+
+ def domain_device_add(self, id, info):
+ """Add a device to a domain.
+ """
+ pass
+
+ def domain_device_remove(self, id, dev):
+ """Delete a device from a domain.
+ """
+ pass
+
+ def domain_device_configure(self, id, dev, info):
+ """Configure a domain device.
+ """
+ pass
+
+ #============================================================================
+ # Backward compatibility stuff from here on.
+
+ def domain_pincpu(self, dom, cpu):
+ dom = int(dom)
+ return xc.domain_pincpu(dom, cpu)
+
+ def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
+ dom = int(dom)
+ return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
+ warp=warp, warpl=warpl, warpu=warpu)
+
+ def domain_cpu_bvt_get(self, dom):
+ dom = int(dom)
+ return xc.bvtsched_domain_get(dom)
+
+ def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
+ dom = int(dom)
+ return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
+
+ def domain_cpu_atropos_get(self, dom):
+ dom = int(dom)
+ return xc.atropos_domain_get(dom)
+
+ def domain_vif_ls(self, dom):
+ dominfo = self.domain_get(dom)
+ if not dominfo: return None
+ devs = dominfo.get_devices('vif')
+ return range(0, len(devs))
+
+ def domain_vif_get(self, dom, vif):
+ dominfo = self.domain_get(dom)
+ if not dominfo: return None
+ return dominfo.get_device_by_index(vif)
+
+ def domain_vif_stats(self, dom, vif):
+ dom = int(dom)
+ return xc.vif_stats_get(dom=dom, vif=vif)
+
+ def domain_vif_ip_add(self, dom, vif, ip):
+ dom = int(dom)
+ return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
+
+ def domain_vif_scheduler_set(self, dom, vif, bytes, usecs):
+ dom = int(dom)
+ return xc.xc_vif_scheduler_set(dom=dom, vif=vif,
+ credit_bytes=bytes, credit_usecs=usecs)
+
+ def domain_vif_scheduler_get(self, dom, vif):
+ dom = int(dom)
+ return xc.vif_scheduler_get(dom=dom, vif=vif)
+
+ def domain_vbd_ls(self, dom):
+ dominfo = self.domain_get(dom)
+ if not dominfo: return []
+ devs = dominfo.get_devices('vbd')
+ return [ sxp.child_value(v, 'dev') for v in devs ]
+
+ def domain_vbd_get(self, dom, vbd):
+ dominfo = self.domain_get(dom)
+ if not dominfo: return None
+ devs = dominfo.get_devices('vbd')
+ for v in devs:
+ if sxp.child_value(v, 'dev') == vbd:
+ return v
+ return None
+
+ def domain_vbd_add(self, dom, uname, dev, mode):
+ dom = int(dom)
+ vbd = vm.make_disk(dom, uname, dev, mode)
+ return vbd
+
+ def domain_vbd_remove(self, dom, dev):
+ dom = int(dom)
+ vbd = xenctl.vdisk.blkdev_name_to_number(dev)
+ if vbd < 0: return vbd
+ err = xc.vbd_destroy(dom, vbd)
+ if err < 0: return err
+ return vbd
+
+ def domain_shadow_control(self, dom, op):
+ dom = int(dom)
+ return xc.shadow_control(dom, op)
+
+ #============================================================================
+
+def instance():
+ global inst
+ try:
+ inst
+ except:
+ inst = XendDomain()
+ return inst