diff options
Diffstat (limited to 'tools/xenmgr/lib/XendDomain.py')
-rw-r--r-- | tools/xenmgr/lib/XendDomain.py | 347 |
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 |