mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
bitkeeper revision 1.1108.24.2 (4108d1f8mh1HwCuBJAKjn8UuBU4wTA)
Change to supporting reference to domain by name or id and make xm tools use names.
This commit is contained in:
1 parent
9609e3f87d
commit
625ccdb6b9
12 files changed
+423
-377
No files matched your search
+160
-133
@@ -39,15 +39,23 @@ class XendDomain:
|
||||
dbpath = "domain"
|
||||
|
||||
"""Table of domain info indexed by domain id."""
|
||||
domain = {}
|
||||
domain_by_id = {}
|
||||
domain_by_name = {}
|
||||
|
||||
"""Table of domains to restart, indexed by domain id."""
|
||||
restarts = {}
|
||||
restarts_by_id = {}
|
||||
restarts_by_name = {}
|
||||
|
||||
"""Table of delayed calls."""
|
||||
schedule = {}
|
||||
|
||||
def __init__(self):
|
||||
# Hack alert. Python does not support mutual imports, but XendDomainInfo
|
||||
# needs access to the XendDomain instance to look up domains. Attempting
|
||||
# to import XendDomain from XendDomainInfo causes unbounded recursion.
|
||||
# So we stuff the XendDomain instance (self) into XendDomainInfo's
|
||||
# namespace as 'xd'.
|
||||
XendDomainInfo.xd = self
|
||||
# Table of domain info indexed by domain id.
|
||||
self.db = XendDB.XendDB(self.dbpath)
|
||||
self.domain_db = self.db.fetchall("")
|
||||
@@ -173,7 +181,8 @@ class XendDomain:
|
||||
@return: deferred
|
||||
"""
|
||||
def cbok(dominfo):
|
||||
self.domain[dominfo.id] = dominfo
|
||||
self.domain_by_id[dominfo.id] = dominfo
|
||||
self.domain_by_name[dominfo.name] = dominfo
|
||||
if dominfo.restart_pending():
|
||||
self.domain_restart_add(dominfo)
|
||||
|
||||
@@ -181,17 +190,17 @@ class XendDomain:
|
||||
deferred.addCallback(cbok)
|
||||
return deferred
|
||||
|
||||
def _add_domain(self, id, info, notify=1):
|
||||
def _add_domain(self, info, notify=1):
|
||||
"""Add a domain entry to the tables.
|
||||
|
||||
@param id: domain id
|
||||
@param info: domain info object
|
||||
@param notify: send a domain created event if true
|
||||
"""
|
||||
self.domain[id] = info
|
||||
self.domain_db[id] = info.sxpr()
|
||||
self.sync_domain(id)
|
||||
if notify: eserver.inject('xend.domain.created', id)
|
||||
self.domain_by_id[info.id] = info
|
||||
self.domain_db[info.id] = info.sxpr()
|
||||
self.domain_by_name[info.name] = info
|
||||
self.sync_domain(info.id)
|
||||
if notify: eserver.inject('xend.domain.created', info.name)
|
||||
|
||||
def _delete_domain(self, id, notify=1):
|
||||
"""Remove a domain from the tables.
|
||||
@@ -199,9 +208,12 @@ class XendDomain:
|
||||
@param id: domain id
|
||||
@param notify: send a domain died event if true
|
||||
"""
|
||||
if id in self.domain:
|
||||
if notify: eserver.inject('xend.domain.died', id)
|
||||
del self.domain[id]
|
||||
if id in self.domain_by_id:
|
||||
info = self.domain_by_id[id]
|
||||
if notify: eserver.inject('xend.domain.died', info.name)
|
||||
if info.name in self.domain_by_name:
|
||||
del self.domain_by_name[info.name]
|
||||
del self.domain_by_id[id]
|
||||
if id in self.domain_db:
|
||||
del self.domain_db[id]
|
||||
self.db.delete(id)
|
||||
@@ -229,7 +241,7 @@ class XendDomain:
|
||||
if reason in ['poweroff', 'reboot']:
|
||||
self.domain_restart_schedule(id, reason)
|
||||
self.final_domain_destroy(id)
|
||||
if len(self.restarts):
|
||||
if self.domain_restarts_exist():
|
||||
self.domain_restarts_schedule()
|
||||
|
||||
def refresh(self):
|
||||
@@ -243,14 +255,14 @@ class XendDomain:
|
||||
for d in domlist:
|
||||
id = str(d['dom'])
|
||||
doms[id] = d
|
||||
if id not in self.domain:
|
||||
if id not in self.domain_by_id:
|
||||
savedinfo = None
|
||||
deferred = XendDomainInfo.vm_recreate(savedinfo, d)
|
||||
def cbok(dominfo):
|
||||
self._add_domain(dominfo.id, dominfo)
|
||||
self._add_domain(dominfo)
|
||||
deferred.addCallback(cbok)
|
||||
# Remove entries for domains that no longer exist.
|
||||
for d in self.domain.values():
|
||||
for d in self.domain_by_id.values():
|
||||
info = doms.get(d.id)
|
||||
if info:
|
||||
d.update(info)
|
||||
@@ -263,7 +275,7 @@ class XendDomain:
|
||||
|
||||
@param id: domain id
|
||||
"""
|
||||
dominfo = self.domain.get(id)
|
||||
dominfo = self.domain_by_id.get(id)
|
||||
if dominfo:
|
||||
self.domain_db[id] = dominfo.sxpr()
|
||||
self.sync_domain(id)
|
||||
@@ -283,17 +295,25 @@ class XendDomain:
|
||||
raise
|
||||
pass
|
||||
else:
|
||||
d = self.domain.get(id)
|
||||
d = self.domain_by_id.get(id)
|
||||
if d:
|
||||
d.update(dominfo[0])
|
||||
|
||||
def domain_ls(self):
|
||||
"""Get list of domain ids.
|
||||
"""Get list of domain names.
|
||||
|
||||
@return: domain ids
|
||||
@return: domain names
|
||||
"""
|
||||
self.refresh()
|
||||
return self.domain.keys()
|
||||
return self.domain_by_name.keys()
|
||||
|
||||
def domain_ls_ids(self):
|
||||
"""Get list of domain ids.
|
||||
|
||||
@return: domain names
|
||||
"""
|
||||
self.refresh()
|
||||
return self.domain_by_id.keys()
|
||||
|
||||
def domains(self):
|
||||
"""Get list of domain objects.
|
||||
@@ -301,7 +321,7 @@ class XendDomain:
|
||||
@return: domain objects
|
||||
"""
|
||||
self.refresh()
|
||||
return self.domain.values()
|
||||
return self.domain_by_id.values()
|
||||
|
||||
def domain_create(self, config):
|
||||
"""Create a domain from a configuration.
|
||||
@@ -310,7 +330,7 @@ class XendDomain:
|
||||
@return: deferred
|
||||
"""
|
||||
def cbok(dominfo):
|
||||
self._add_domain(dominfo.id, dominfo)
|
||||
self._add_domain(dominfo)
|
||||
return dominfo
|
||||
deferred = XendDomainInfo.vm_create(config)
|
||||
deferred.addCallback(cbok)
|
||||
@@ -323,7 +343,7 @@ class XendDomain:
|
||||
@return: deferred
|
||||
"""
|
||||
def cbok(dominfo):
|
||||
self._add_domain(dominfo.id, dominfo)
|
||||
self._add_domain(dominfo)
|
||||
return dominfo
|
||||
log.info("Restarting domain: id=%s name=%s", dominfo.id, dominfo.name)
|
||||
deferred = dominfo.restart()
|
||||
@@ -338,15 +358,14 @@ class XendDomain:
|
||||
@param config: configuration
|
||||
@return: deferred
|
||||
"""
|
||||
log.debug('domain_configure> id=%s config=%s', id, str(config))
|
||||
dom = int(id)
|
||||
dominfo = self.domain_get(dom)
|
||||
dominfo = self.domain_get(id)
|
||||
if not dominfo:
|
||||
raise XendError("Invalid domain: " + str(id))
|
||||
log.debug('domain_configure> id=%s config=%s', id, str(config))
|
||||
if dominfo.config:
|
||||
raise XendError("Domain already configured: " + str(id))
|
||||
raise XendError("Domain already configured: " + dominfo.name)
|
||||
def cbok(dominfo):
|
||||
self._add_domain(dominfo.id, dominfo)
|
||||
self._add_domain(dominfo)
|
||||
return dominfo
|
||||
deferred = dominfo.construct(config)
|
||||
deferred.addCallback(cbok)
|
||||
@@ -361,7 +380,7 @@ class XendDomain:
|
||||
"""
|
||||
|
||||
def cbok(dominfo):
|
||||
self._add_domain(dominfo.id, dominfo)
|
||||
self._add_domain(dominfo)
|
||||
return dominfo
|
||||
deferred = XendDomainInfo.vm_restore(src, progress=progress)
|
||||
deferred.addCallback(cbok)
|
||||
@@ -375,25 +394,39 @@ class XendDomain:
|
||||
"""
|
||||
id = str(id)
|
||||
self.refresh_domain(id)
|
||||
return self.domain.get(id)
|
||||
|
||||
return self.domain_by_id.get(id)
|
||||
|
||||
def domain_lookup(self, name):
|
||||
name = str(name)
|
||||
dominfo = self.domain_by_name.get(name) or self.domain_by_id.get(name)
|
||||
if dominfo:
|
||||
return dominfo
|
||||
raise XendError('invalid domain:' + name)
|
||||
|
||||
def domain_exists(self, name):
|
||||
name = str(name)
|
||||
if self.domain_by_name.get(name) or self.domain_by_id.get(name):
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def domain_unpause(self, id):
|
||||
"""Unpause domain execution.
|
||||
|
||||
@param id: domain id
|
||||
"""
|
||||
dom = int(id)
|
||||
eserver.inject('xend.domain.unpause', id)
|
||||
return xc.domain_unpause(dom=dom)
|
||||
dominfo = self.domain_lookup(id)
|
||||
eserver.inject('xend.domain.unpause', dominfo.name)
|
||||
return xc.domain_unpause(dom=dominfo.dom)
|
||||
|
||||
def domain_pause(self, id):
|
||||
"""Pause domain execution.
|
||||
|
||||
@param id: domain id
|
||||
"""
|
||||
dom = int(id)
|
||||
eserver.inject('xend.domain.pause', id)
|
||||
return xc.domain_pause(dom=dom)
|
||||
dominfo = self.domain_lookup(id)
|
||||
eserver.inject('xend.domain.pause', dominfo.name)
|
||||
return xc.domain_pause(dom=dominfo.dom)
|
||||
|
||||
def domain_shutdown(self, id, reason='poweroff'):
|
||||
"""Shutdown domain (nicely).
|
||||
@@ -406,18 +439,15 @@ class XendDomain:
|
||||
@param id: domain id
|
||||
@param reason: shutdown type: poweroff, reboot, suspend, halt
|
||||
"""
|
||||
dom = int(id)
|
||||
id = str(id)
|
||||
if dom <= 0:
|
||||
return 0
|
||||
dominfo = self.domain_lookup(id)
|
||||
if reason == 'halt':
|
||||
self.domain_restart_cancel(id)
|
||||
self.domain_restart_cancel(dominfo.id)
|
||||
else:
|
||||
self.domain_restart_schedule(id, reason, force=1)
|
||||
eserver.inject('xend.domain.shutdown', [id, reason])
|
||||
self.domain_restart_schedule(dominfo.id, reason, force=1)
|
||||
eserver.inject('xend.domain.shutdown', [dominfo.name, reason])
|
||||
if reason == 'halt':
|
||||
reason = 'poweroff'
|
||||
val = xend.domain_shutdown(dom, reason)
|
||||
val = xend.domain_shutdown(dominfo.id, reason)
|
||||
self.refresh_schedule()
|
||||
return val
|
||||
|
||||
@@ -428,10 +458,10 @@ class XendDomain:
|
||||
@param reason: shutdown reason
|
||||
"""
|
||||
log.debug('domain_restart_schedule> %s %s %d', id, reason, force)
|
||||
dominfo = self.domain.get(id)
|
||||
dominfo = self.domain_lookup(id)
|
||||
if not dominfo:
|
||||
return
|
||||
if id in self.restarts:
|
||||
if dominfo.id in self.restarts_by_id:
|
||||
return
|
||||
restart = (force and reason == 'reboot') or dominfo.restart_needed(reason)
|
||||
if restart:
|
||||
@@ -439,8 +469,9 @@ class XendDomain:
|
||||
self.domain_restart_add(dominfo)
|
||||
|
||||
def domain_restart_add(self, dominfo):
|
||||
self.restarts[dominfo.id] = dominfo
|
||||
log.info('Scheduling restart for domain: id=%s name=%s', dominfo.id, dominfo.name)
|
||||
self.restarts_by_name[dominfo.name] = dominfo
|
||||
self.restarts_by_id[dominfo.id] = dominfo
|
||||
log.info('Scheduling restart for domain: name=%s id=%s', dominfo.name, dominfo.id)
|
||||
self.domain_restarts_schedule()
|
||||
|
||||
def domain_restart_cancel(self, id):
|
||||
@@ -448,53 +479,57 @@ class XendDomain:
|
||||
|
||||
@param id: domain id
|
||||
"""
|
||||
dominfo = self.restarts.get(id)
|
||||
dominfo = self.restarts_by_id.get(id) or self.restarts_by_name.get(id)
|
||||
if dominfo:
|
||||
log.info('Cancelling restart for domain: id=%s name=%s', dominfo.id, dominfo.name)
|
||||
log.info('Cancelling restart for domain: name=%s id=%s', dominfo.name, dominfo.id)
|
||||
dominfo.restart_cancel()
|
||||
del self.restarts[id]
|
||||
del self.restarts_by_id[dominfo.id]
|
||||
del self.restarts_by_name[dominfo.name]
|
||||
|
||||
def domain_restarts(self):
|
||||
"""Execute any scheduled domain restarts for domains that have gone.
|
||||
"""
|
||||
self.domain_restarts_cancel()
|
||||
for id in self.restarts.keys():
|
||||
if id in self.domain:
|
||||
for dominfo in self.restarts_by_id.values():
|
||||
if dominfo.id in self.domain_by_id:
|
||||
# Don't execute restart for domains still running.
|
||||
continue
|
||||
dominfo = self.restarts[id]
|
||||
# Remove it from the restarts.
|
||||
del self.restarts[id]
|
||||
del self.restarts_by_id[dominfo.id]
|
||||
del self.restarts_by_name[dominfo.name]
|
||||
try:
|
||||
def cbok(dominfo):
|
||||
log.info('Restarted domain id=%s as %s', id, dominfo.id)
|
||||
log.info('Restarted domain name=%s id=%s', dominfo.name, dominfo.id)
|
||||
self.domain_unpause(dominfo.id)
|
||||
def cberr(err):
|
||||
log.exception("Delayed exception restarting domain: id=%s", id)
|
||||
log.exception("Delayed exception restarting domain: name=%s id=%s",
|
||||
dominfo.name, dominfo.id)
|
||||
deferred = self.domain_restart(dominfo)
|
||||
deferred.addCallback(cbok)
|
||||
deferred.addErrback(cberr)
|
||||
except:
|
||||
log.exception("Exception restarting domain: id=%s", id)
|
||||
if len(self.restarts):
|
||||
log.exception("Exception restarting domain: name=%s id=%s",
|
||||
dominfo.name, dominfo.id)
|
||||
if self.domain_restarts_exist():
|
||||
# Run again later if any restarts remain.
|
||||
self.refresh_schedule(delay=5)
|
||||
|
||||
def domain_restarts_exist(self):
|
||||
return len(self.restarts_by_id)
|
||||
|
||||
def final_domain_destroy(self, id):
|
||||
"""Final destruction of a domain..
|
||||
|
||||
@param id: domain id
|
||||
"""
|
||||
dom = int(id)
|
||||
if dom <= 0:
|
||||
return 0
|
||||
log.info('Destroying domain: id=%s', str(id))
|
||||
eserver.inject('xend.domain.destroy', id)
|
||||
dominfo = self.domain.get(id)
|
||||
dominfo = self.domain_lookup(id)
|
||||
log.info('Destroying domain: name=%s', dominfo.name)
|
||||
eserver.inject('xend.domain.destroy', dominfo.name)
|
||||
if dominfo:
|
||||
val = dominfo.destroy()
|
||||
else:
|
||||
val = xc.domain_destroy(dom=dom)
|
||||
#todo
|
||||
val = xc.domain_destroy(dom=dominfo.dom)
|
||||
return val
|
||||
|
||||
def domain_destroy(self, id, reason='halt'):
|
||||
@@ -504,7 +539,6 @@ class XendDomain:
|
||||
|
||||
@param id: domain id
|
||||
"""
|
||||
id = str(id)
|
||||
if reason == 'halt':
|
||||
self.domain_restart_cancel(id)
|
||||
elif reason == 'reboot':
|
||||
@@ -522,9 +556,9 @@ class XendDomain:
|
||||
# Need a cancel too?
|
||||
# Don't forget to cancel restart for it.
|
||||
print 'domain_migrate>', id, dst
|
||||
dom = int(id)
|
||||
dominfo = self.domain_lookup(id)
|
||||
xmigrate = XendMigrate.instance()
|
||||
val = xmigrate.migrate_begin(dom, dst)
|
||||
val = xmigrate.migrate_begin(dominfo.id, dst)
|
||||
print 'domain_migrate<', val
|
||||
return val
|
||||
|
||||
@@ -536,9 +570,9 @@ class XendDomain:
|
||||
@param progress: output progress if true
|
||||
@return: deferred
|
||||
"""
|
||||
dom = int(id)
|
||||
dominfo = self.domain_lookup(id)
|
||||
xmigrate = XendMigrate.instance()
|
||||
return xmigrate.save_begin(dom, dst)
|
||||
return xmigrate.save_begin(dominfo.id, dst)
|
||||
|
||||
def domain_pincpu(self, dom, cpu):
|
||||
"""Pin a domain to a cpu.
|
||||
@@ -546,156 +580,149 @@ class XendDomain:
|
||||
@param dom: domain
|
||||
@param cpu: cpu number
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.domain_pincpu(dom, cpu)
|
||||
dominfo = self.domain_lookup(id)
|
||||
return xc.domain_pincpu(itn(dominfo.id), cpu)
|
||||
|
||||
def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
|
||||
def domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
|
||||
"""Set BVT (Borrowed Virtual Time) scheduler parameters for a domain.
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
|
||||
dominfo = self.domain_lookup(id)
|
||||
return xc.bvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv,
|
||||
warp=warp, warpl=warpl, warpu=warpu)
|
||||
|
||||
def domain_cpu_bvt_get(self, dom):
|
||||
def domain_cpu_bvt_get(self, id):
|
||||
"""Get BVT (Borrowed Virtual Time) scheduler parameters for a domain.
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.bvtsched_domain_get(dom)
|
||||
dominfo = self.domain_lookup(id)
|
||||
return xc.bvtsched_domain_get(dominfo.dom)
|
||||
|
||||
def domain_cpu_fbvt_set(self, dom, mcuadv, warp, warpl, warpu):
|
||||
def domain_cpu_fbvt_set(self, id, mcuadv, warp, warpl, warpu):
|
||||
"""Set FBVT (Fair Borrowed Virtual Time) scheduler parameters for a domain.
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.fbvtsched_domain_set(dom=dom, mcuadv=mcuadv,
|
||||
dominfo = self.domain_lookup(id)
|
||||
return xc.fbvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv,
|
||||
warp=warp, warpl=warpl, warpu=warpu)
|
||||
|
||||
def domain_cpu_fbvt_get(self, dom):
|
||||
def domain_cpu_fbvt_get(self, id):
|
||||
"""Get FBVT (Fair Borrowed Virtual Time) scheduler parameters for a domain.
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.fbvtsched_domain_get(dom)
|
||||
dominfo = self.domain_lookup(id)
|
||||
return xc.fbvtsched_domain_get(dominfo.dom)
|
||||
|
||||
def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
|
||||
def domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
|
||||
"""Set Atropos scheduler parameters for a domain.
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
|
||||
dominfo = self.domain_lookup(id)
|
||||
return xc.atropos_domain_set(dominfo.dom, period, slice, latency, xtratime)
|
||||
|
||||
def domain_cpu_atropos_get(self, dom):
|
||||
def domain_cpu_atropos_get(self, id):
|
||||
"""Get Atropos scheduler parameters for a domain.
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.atropos_domain_get(dom)
|
||||
dominfo = self.domain_lookup(id)
|
||||
return xc.atropos_domain_get(dominfo.dom)
|
||||
|
||||
def domain_device_create(self, dom, devconfig):
|
||||
def domain_device_create(self, id, devconfig):
|
||||
"""Create a new device for a domain.
|
||||
|
||||
@param dom: domain id
|
||||
@param id: domain id
|
||||
@param devconfig: device configuration
|
||||
@return: deferred
|
||||
"""
|
||||
dom = int(dom)
|
||||
dominfo = self.domain_get(dom)
|
||||
if not dominfo:
|
||||
raise XendError("invalid domain:" + str(dom))
|
||||
dominfo = self.domain_lookup(id)
|
||||
self.refresh_schedule()
|
||||
val = dominfo.device_create(devconfig)
|
||||
self.update_domain(dominfo.id)
|
||||
return val
|
||||
|
||||
def domain_device_destroy(self, dom, type, idx):
|
||||
def domain_device_destroy(self, id, type, idx):
|
||||
"""Destroy a device.
|
||||
|
||||
@param dom: domain id
|
||||
@param id: domain id
|
||||
@param type: device type
|
||||
@param idx: device index
|
||||
"""
|
||||
dom = int(dom)
|
||||
dominfo = self.domain_get(dom)
|
||||
if not dominfo:
|
||||
raise XendError("invalid domain:" + str(dom))
|
||||
dominfo = self.domain_lookup(id)
|
||||
self.refresh_schedule()
|
||||
val = dominfo.device_destroy(type, idx)
|
||||
self.update_domain(dominfo.id)
|
||||
return val
|
||||
|
||||
def domain_devtype_ls(self, dom, type):
|
||||
def domain_devtype_ls(self, id, type):
|
||||
"""Get list of device indexes for a domain.
|
||||
|
||||
@param dom: domain
|
||||
@param id: domain
|
||||
@param type: device type
|
||||
@return: device indexes
|
||||
"""
|
||||
dominfo = self.domain_get(dom)
|
||||
if not dominfo: return None
|
||||
dominfo = self.domain_lookup(id)
|
||||
devs = dominfo.get_devices(type)
|
||||
return range(0, len(devs))
|
||||
#return range(0, len(devs))
|
||||
return devs
|
||||
|
||||
def domain_devtype_get(self, dom, type, idx):
|
||||
def domain_devtype_get(self, id, type, idx):
|
||||
"""Get a device from a domain.
|
||||
|
||||
@param dom: domain
|
||||
@param id: domain
|
||||
@param type: device type
|
||||
@param idx: device index
|
||||
@return: device object (or None)
|
||||
"""
|
||||
dominfo = self.domain_get(dom)
|
||||
if not dominfo: return None
|
||||
dominfo = self.domain_lookup(id)
|
||||
return dominfo.get_device_by_index(type, idx)
|
||||
|
||||
def domain_vif_ls(self, dom):
|
||||
def domain_vif_ls(self, id):
|
||||
"""Get list of virtual network interface (vif) indexes for a domain.
|
||||
|
||||
@param dom: domain
|
||||
@param id: domain
|
||||
@return: vif indexes
|
||||
"""
|
||||
return self.domain_devtype_ls(dom, 'vif')
|
||||
return self.domain_devtype_ls(id, 'vif')
|
||||
|
||||
def domain_vif_get(self, dom, vif):
|
||||
def domain_vif_get(self, id, vif):
|
||||
"""Get a virtual network interface (vif) from a domain.
|
||||
|
||||
@param dom: domain
|
||||
@param id: domain
|
||||
@param vif: vif index
|
||||
@return: vif device object (or None)
|
||||
"""
|
||||
return self.domain_devtype_get(dom, 'vif', vif)
|
||||
return self.domain_devtype_get(id, 'vif', vif)
|
||||
|
||||
def domain_vbd_ls(self, dom):
|
||||
def domain_vbd_ls(self, id):
|
||||
"""Get list of virtual block device (vbd) indexes for a domain.
|
||||
|
||||
@param dom: domain
|
||||
@param id: domain
|
||||
@return: vbd indexes
|
||||
"""
|
||||
return self.domain_devtype_ls(dom, 'vbd')
|
||||
return self.domain_devtype_ls(id, 'vbd')
|
||||
|
||||
def domain_vbd_get(self, dom, vbd):
|
||||
def domain_vbd_get(self, id, vbd):
|
||||
"""Get a virtual block device (vbd) from a domain.
|
||||
|
||||
@param dom: domain
|
||||
@param id: domain
|
||||
@param vbd: vbd index
|
||||
@return: vbd device (or None)
|
||||
"""
|
||||
return self.domain_devtype_get(dom, 'vbd', vbd)
|
||||
return self.domain_devtype_get(id, 'vbd', vbd)
|
||||
|
||||
def domain_shadow_control(self, dom, op):
|
||||
def domain_shadow_control(self, id, op):
|
||||
"""Shadow page control.
|
||||
|
||||
@param dom: domain
|
||||
@param id: domain
|
||||
@param op: operation
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.shadow_control(dom, op)
|
||||
dominfo = self.domain_lookup(id)
|
||||
return xc.shadow_control(dominfo.dom, op)
|
||||
|
||||
def domain_maxmem_set(self, dom, mem):
|
||||
def domain_maxmem_set(self, id, mem):
|
||||
"""Set the memory limit for a domain.
|
||||
|
||||
@param dom: domain
|
||||
@param mem: memory limit (in MB)
|
||||
@return: 0 on success, -1 on error
|
||||
"""
|
||||
dom = int(dom)
|
||||
dominfo = self.domain_lookup(id)
|
||||
maxmem = int(mem) * 1024
|
||||
return xc.domain_setmaxmem(dom, maxmem_kb = maxmem)
|
||||
return xc.domain_setmaxmem(dominfo.dom, maxmem_kb = maxmem)
|
||||
|
||||
|
||||
def instance():
|
||||
|
||||
@@ -193,8 +193,8 @@ config_handlers = {}
|
||||
def add_config_handler(name, h):
|
||||
"""Add a handler for a config field.
|
||||
|
||||
name field name
|
||||
h handler: fn(vm, config, field, index)
|
||||
@param name: field name
|
||||
@param h: handler: fn(vm, config, field, index)
|
||||
"""
|
||||
config_handlers[name] = h
|
||||
|
||||
@@ -212,16 +212,15 @@ image_handlers = {}
|
||||
|
||||
def add_image_handler(name, h):
|
||||
"""Add a handler for an image type
|
||||
name image type
|
||||
h handler: fn(config, name, memory, image)
|
||||
@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.
|
||||
name image type
|
||||
|
||||
returns handler or None
|
||||
@param name: image type
|
||||
@return: handler or None
|
||||
"""
|
||||
return image_handlers.get(name)
|
||||
|
||||
@@ -233,17 +232,16 @@ device_handlers = {}
|
||||
def add_device_handler(name, h):
|
||||
"""Add a handler for a device type.
|
||||
|
||||
name device type
|
||||
h handler: fn(vm, dev)
|
||||
@param name: device type
|
||||
@param h: handler: fn(vm, dev)
|
||||
"""
|
||||
device_handlers[name] = h
|
||||
|
||||
def get_device_handler(name):
|
||||
"""Get the handler for a device type.
|
||||
|
||||
name device type
|
||||
|
||||
returns handler or None
|
||||
@param name : device type
|
||||
@return; handler or None
|
||||
"""
|
||||
return device_handlers.get(name)
|
||||
|
||||
@@ -252,10 +250,9 @@ def vm_create(config):
|
||||
If a vm has been partially created and there is an error it
|
||||
is destroyed.
|
||||
|
||||
config configuration
|
||||
|
||||
returns Deferred
|
||||
raises VmError for invalid configuration
|
||||
@param config configuration
|
||||
@return: Deferred
|
||||
@raise: VmError for invalid configuration
|
||||
"""
|
||||
vm = XendDomainInfo()
|
||||
return vm.construct(config)
|
||||
@@ -314,21 +311,27 @@ def vm_restore(src, progress=0):
|
||||
return deferred
|
||||
|
||||
def dom_get(dom):
|
||||
"""Get info from xen for an existing domain.
|
||||
|
||||
@param dom: domain id
|
||||
@return: info or None
|
||||
"""
|
||||
domlist = xc.domain_getinfo(dom=dom)
|
||||
if domlist and dom == domlist[0]['dom']:
|
||||
return domlist[0]
|
||||
return None
|
||||
|
||||
|
||||
def append_deferred(dlist, v):
|
||||
"""Append a value to a deferred list if it is a deferred.
|
||||
|
||||
@param dlist: list of deferreds
|
||||
@param v: value to add
|
||||
"""
|
||||
if isinstance(v, defer.Deferred):
|
||||
dlist.append(v)
|
||||
|
||||
def _vm_configure1(val, vm):
|
||||
d = vm.create_devices()
|
||||
def cbok(x):
|
||||
return x
|
||||
d.addCallback(cbok)
|
||||
d.addCallback(_vm_configure2, vm)
|
||||
return d
|
||||
|
||||
@@ -348,7 +351,7 @@ class XendDomainInfo:
|
||||
|
||||
"""Minimum time between domain restarts in seconds.
|
||||
"""
|
||||
MINIMUM_RESTART_TIME = 10
|
||||
MINIMUM_RESTART_TIME = 20
|
||||
|
||||
def __init__(self):
|
||||
self.recreate = 0
|
||||
@@ -363,6 +366,7 @@ class XendDomainInfo:
|
||||
self.cmdline = None
|
||||
self.console = None
|
||||
self.devices = {}
|
||||
self.device_index = {}
|
||||
self.configs = []
|
||||
self.info = None
|
||||
self.ipaddrs = []
|
||||
@@ -378,9 +382,13 @@ class XendDomainInfo:
|
||||
self.console_port = None
|
||||
|
||||
def setdom(self, dom):
|
||||
"""Set the domain id.
|
||||
|
||||
@param dom: domain id
|
||||
"""
|
||||
self.dom = int(dom)
|
||||
self.id = str(dom)
|
||||
|
||||
|
||||
def update(self, info):
|
||||
"""Update with info from xc.domain_getinfo().
|
||||
"""
|
||||
@@ -437,13 +445,39 @@ class XendDomainInfo:
|
||||
sxpr.append(['config', self.config])
|
||||
return sxpr
|
||||
|
||||
def check_name(self, name):
|
||||
"""Check if a vm name is valid. Valid names start with a non-digit
|
||||
and contain alphabetic characters, digits, or characters in '_-.'.
|
||||
The same name cannot be used for more than one vm at the same time.
|
||||
|
||||
@param name: name
|
||||
@raise: VMerror if invalid
|
||||
"""
|
||||
if name is None or name == '':
|
||||
raise VmError('missing vm name')
|
||||
if name[0] in string.digits:
|
||||
raise VmError('invalid vm name')
|
||||
for c in name:
|
||||
if c in string.digits: continue
|
||||
if c in '_-.': continue
|
||||
if c in string.ascii_letters: continue
|
||||
raise VmError('invalid vm name')
|
||||
# See comment in XendDomain constructor about 'xd'.
|
||||
if xd.domain_exists(name):
|
||||
raise VmError('vm name clash: ' + name)
|
||||
|
||||
def construct(self, config):
|
||||
"""Construct the vm instance from its configuration.
|
||||
|
||||
@param config: configuration
|
||||
@return: deferred
|
||||
@raise: VmError on error
|
||||
"""
|
||||
# todo - add support for scheduling params?
|
||||
self.config = config
|
||||
try:
|
||||
self.name = sxp.child_value(config, 'name')
|
||||
if self.name is None:
|
||||
raise VmError('missing domain name')
|
||||
self.check_name(self.name)
|
||||
self.memory = int(sxp.child_value(config, 'memory'))
|
||||
if self.memory is None:
|
||||
raise VmError('missing memory size')
|
||||
@@ -462,12 +496,9 @@ class XendDomainInfo:
|
||||
raise VmError('unknown image type: ' + image_name)
|
||||
image_handler(self, image)
|
||||
deferred = self.configure()
|
||||
def cbok(x):
|
||||
return x
|
||||
def cberr(err):
|
||||
self.destroy()
|
||||
return err
|
||||
deferred.addCallback(cbok)
|
||||
deferred.addErrback(cberr)
|
||||
except StandardError, ex:
|
||||
# Catch errors, cleanup and re-raise.
|
||||
@@ -478,8 +509,10 @@ class XendDomainInfo:
|
||||
def config_devices(self, name):
|
||||
"""Get a list of the 'device' nodes of a given type from the config.
|
||||
|
||||
name device type
|
||||
return list of device configs
|
||||
@param name: device type
|
||||
@type name: string
|
||||
@return: device configs
|
||||
@rtype: list
|
||||
"""
|
||||
devices = []
|
||||
for d in sxp.children(self.config, 'device'):
|
||||
@@ -490,31 +523,57 @@ class XendDomainInfo:
|
||||
return devices
|
||||
|
||||
def config_device(self, type, idx):
|
||||
"""Get a device config from the device nodes of a given type
|
||||
from the config.
|
||||
|
||||
@param type: device type
|
||||
@type type: string
|
||||
@param idx: index
|
||||
@type idx: int
|
||||
@return config or None
|
||||
"""
|
||||
devs = self.config_devices(type)
|
||||
if 0 <= idx < len(devs):
|
||||
return devs[idx]
|
||||
else:
|
||||
return None
|
||||
|
||||
def next_device_index(self, type):
|
||||
"""Get the next index for a given device type.
|
||||
|
||||
@param type: device type
|
||||
@type type: string
|
||||
@return device index
|
||||
@rtype: int
|
||||
"""
|
||||
idx = self.device_index.get(type, 0)
|
||||
self.device_index[type] = idx + 1
|
||||
return idx
|
||||
|
||||
def add_device(self, type, dev):
|
||||
"""Add a device to a virtual machine.
|
||||
|
||||
dev device to add
|
||||
@param type: device type
|
||||
@param dev: device to add
|
||||
"""
|
||||
dl = self.devices.get(type, [])
|
||||
dl.append(dev)
|
||||
self.devices[type] = dl
|
||||
|
||||
def get_devices(self, type):
|
||||
"""Get a list of the devices of a given type.
|
||||
|
||||
@param type: device type
|
||||
@return: devices
|
||||
"""
|
||||
val = self.devices.get(type, [])
|
||||
return val
|
||||
|
||||
def get_device_by_id(self, type, id):
|
||||
"""Get the device with the given id.
|
||||
|
||||
id device id
|
||||
|
||||
returns device or None
|
||||
@param id: device id
|
||||
@return: device or None
|
||||
"""
|
||||
dl = self.get_devices(type)
|
||||
for d in dl:
|
||||
@@ -525,20 +584,20 @@ class XendDomainInfo:
|
||||
def get_device_by_index(self, type, idx):
|
||||
"""Get the device with the given index.
|
||||
|
||||
idx device index
|
||||
|
||||
returns device or None
|
||||
@param idx: device index
|
||||
@return: device or None
|
||||
"""
|
||||
idx = str(idx)
|
||||
dl = self.get_devices(type)
|
||||
if 0 <= idx < len(dl):
|
||||
return dl[idx]
|
||||
else:
|
||||
return None
|
||||
for d in dl:
|
||||
if d.getidx() == idx:
|
||||
return d
|
||||
return None
|
||||
|
||||
def add_config(self, val):
|
||||
"""Add configuration data to a virtual machine.
|
||||
|
||||
val data to add
|
||||
@param val: data to add
|
||||
"""
|
||||
self.configs.append(val)
|
||||
|
||||
@@ -661,11 +720,11 @@ class XendDomainInfo:
|
||||
def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
|
||||
"""Create a domain. Builds the image but does not configure it.
|
||||
|
||||
ostype OS type
|
||||
kernel kernel image
|
||||
ramdisk kernel ramdisk
|
||||
cmdline kernel commandline
|
||||
vifs_n number of network interfaces
|
||||
@param ostype: OS type
|
||||
@param kernel: kernel image
|
||||
@param ramdisk: kernel ramdisk
|
||||
@param cmdline: kernel commandline
|
||||
@param vifs_n: number of network interfaces
|
||||
"""
|
||||
if not self.recreate:
|
||||
if not os.path.isfile(kernel):
|
||||
@@ -685,8 +744,8 @@ class XendDomainInfo:
|
||||
def create_devices(self):
|
||||
"""Create the devices for a vm.
|
||||
|
||||
returns Deferred
|
||||
raises VmError for invalid devices
|
||||
@return: Deferred
|
||||
@raise: VmError for invalid devices
|
||||
"""
|
||||
dlist = []
|
||||
devices = sxp.children(self.config, 'device')
|
||||
@@ -730,16 +789,17 @@ class XendDomainInfo:
|
||||
"""
|
||||
dev = self.get_device_by_index(type, idx)
|
||||
if not dev:
|
||||
raise VmError('invalid device: %s %d' % (type, idx))
|
||||
raise VmError('invalid device: %s %s' % (type, idx))
|
||||
devs = self.devices.get(type)
|
||||
if 0 <= idx < len(devs):
|
||||
del devs[idx]
|
||||
dev_config = self.config_device(type, idx)
|
||||
index = devs.index(dev)
|
||||
dev_config = self.config_device(type, index)
|
||||
if dev_config:
|
||||
self.config.remove(['device', dev_config])
|
||||
dev.destroy()
|
||||
|
||||
def configure_console(self):
|
||||
"""Configure the vm console port.
|
||||
"""
|
||||
x = sxp.child_value(self.config, 'console')
|
||||
if x:
|
||||
try:
|
||||
@@ -749,12 +809,20 @@ class XendDomainInfo:
|
||||
self.console_port = port
|
||||
|
||||
def configure_restart(self):
|
||||
"""Configure the vm restart mode.
|
||||
"""
|
||||
r = sxp.child_value(self.config, 'restart', RESTART_ONREBOOT)
|
||||
if r not in restart_modes:
|
||||
raise VmError('invalid restart mode: ' + str(r))
|
||||
self.restart_mode = r;
|
||||
|
||||
def restart_needed(self, reason):
|
||||
"""Determine if the vm needs to be restarted when shutdown
|
||||
for the given reason.
|
||||
|
||||
@param reason: shutdown reason
|
||||
@return 1 if needs restaert, 0 otherwise
|
||||
"""
|
||||
if self.restart_mode == RESTART_NEVER:
|
||||
return 0
|
||||
if self.restart_mode == RESTART_ALWAYS:
|
||||
@@ -764,12 +832,18 @@ class XendDomainInfo:
|
||||
return 0
|
||||
|
||||
def restart_cancel(self):
|
||||
"""Cancel a vm restart.
|
||||
"""
|
||||
self.restart_state = None
|
||||
|
||||
def restarting(self):
|
||||
"""Put the vm into restart mode.
|
||||
"""
|
||||
self.restart_state = STATE_RESTART_PENDING
|
||||
|
||||
def restart_pending(self):
|
||||
"""Test if the vm has a pending restart.
|
||||
"""
|
||||
return self.restart_state == STATE_RESTART_PENDING
|
||||
|
||||
def restart_check(self):
|
||||
@@ -781,7 +855,7 @@ class XendDomainInfo:
|
||||
if self.restart_time is not None:
|
||||
tdelta = tnow - self.restart_time
|
||||
if tdelta < self.MINIMUM_RESTART_TIME:
|
||||
msg = 'VM %d restarting too fast' % self.dom
|
||||
msg = 'VM %s restarting too fast' % self.name
|
||||
log.error(msg)
|
||||
raise VmError(msg)
|
||||
self.restart_time = tnow
|
||||
@@ -830,17 +904,17 @@ class XendDomainInfo:
|
||||
"""
|
||||
if self.blkif_backend:
|
||||
d = defer.Deferred()
|
||||
d.callback(1)
|
||||
d.callback(self)
|
||||
else:
|
||||
d = xend.blkif_create(self.dom, recreate=self.recreate)
|
||||
d.addCallback(_vm_configure1, self)
|
||||
return d
|
||||
|
||||
def dom_configure(self, dom):
|
||||
"""Configure a domain.
|
||||
"""Configure a vm for an existing domain.
|
||||
|
||||
dom domain id
|
||||
returns deferred
|
||||
@param dom: domain id
|
||||
@return: deferred
|
||||
"""
|
||||
d = dom_get(dom)
|
||||
if not d:
|
||||
@@ -860,6 +934,8 @@ class XendDomainInfo:
|
||||
return deferred
|
||||
|
||||
def configure_fields(self):
|
||||
"""Process the vm configuration fields using the registered handlers.
|
||||
"""
|
||||
dlist = []
|
||||
index = {}
|
||||
for field in sxp.children(self.config):
|
||||
@@ -880,11 +956,10 @@ class XendDomainInfo:
|
||||
def vm_image_linux(vm, image):
|
||||
"""Create a VM for a linux image.
|
||||
|
||||
name vm name
|
||||
memory vm memory
|
||||
image image config
|
||||
|
||||
returns vm
|
||||
@param name: vm name
|
||||
@param memory: vm memory
|
||||
@param image: image config
|
||||
@return: vm
|
||||
"""
|
||||
kernel = sxp.child_value(image, "kernel")
|
||||
cmdline = ""
|
||||
@@ -905,11 +980,10 @@ def vm_image_linux(vm, image):
|
||||
def vm_image_netbsd(vm, image):
|
||||
"""Create a VM for a bsd image.
|
||||
|
||||
name vm name
|
||||
memory vm memory
|
||||
image image config
|
||||
|
||||
returns vm
|
||||
@param name: vm name
|
||||
@param memory: vm memory
|
||||
@param image: image config
|
||||
@return: vm
|
||||
"""
|
||||
#todo: Same as for linux. Is that right? If so can unify them.
|
||||
kernel = sxp.child_value(image, "kernel")
|
||||
@@ -932,13 +1006,14 @@ def vm_image_netbsd(vm, image):
|
||||
def vm_dev_vif(vm, val, index):
|
||||
"""Create a virtual network interface (vif).
|
||||
|
||||
vm virtual machine
|
||||
val vif config
|
||||
index vif index
|
||||
@param vm: virtual machine
|
||||
@param val: vif config
|
||||
@param index: vif index
|
||||
@return: deferred
|
||||
"""
|
||||
if vm.netif_backend:
|
||||
raise VmError('vif: vif in netif backend domain')
|
||||
vif = index #todo
|
||||
vif = vm.next_device_index('vif')
|
||||
vmac = sxp.child_value(val, "mac")
|
||||
xend.netif_create(vm.dom, recreate=vm.recreate)
|
||||
log.debug("Creating vif dom=%d vif=%d mac=%s", vm.dom, vif, str(vmac))
|
||||
@@ -954,13 +1029,14 @@ def vm_dev_vif(vm, val, index):
|
||||
def vm_dev_vbd(vm, val, index):
|
||||
"""Create a virtual block device (vbd).
|
||||
|
||||
vm virtual machine
|
||||
val vbd config
|
||||
index vbd index
|
||||
@param vm: virtual machine
|
||||
@param val: vbd config
|
||||
@param index: vbd index
|
||||
@return: deferred
|
||||
"""
|
||||
if vm.blkif_backend:
|
||||
raise VmError('vbd: vbd in blkif backend domain')
|
||||
vdev = index
|
||||
vdev = vm.next_device_index('vif')
|
||||
uname = sxp.child_value(val, 'uname')
|
||||
if not uname:
|
||||
raise VmError('vbd: Missing uname')
|
||||
@@ -978,6 +1054,8 @@ def vm_dev_vbd(vm, val, index):
|
||||
return defer
|
||||
|
||||
def parse_pci(val):
|
||||
"""Parse a pci field.
|
||||
"""
|
||||
if isinstance(val, types.StringType):
|
||||
radix = 10
|
||||
if val.startswith('0x') or val.startswith('0X'):
|
||||
@@ -988,6 +1066,13 @@ def parse_pci(val):
|
||||
return v
|
||||
|
||||
def vm_dev_pci(vm, val, index):
|
||||
"""Add a pci device.
|
||||
|
||||
@param vm: virtual machine
|
||||
@param val: device configuration
|
||||
@param index: device index
|
||||
@return: 0 on success
|
||||
"""
|
||||
bus = sxp.child_value(val, 'bus')
|
||||
if not bus:
|
||||
raise VmError('pci: Missing bus')
|
||||
@@ -1013,78 +1098,21 @@ def vm_dev_pci(vm, val, index):
|
||||
return rc
|
||||
|
||||
|
||||
def vm_field_vfr(vm, config, val, index):
|
||||
"""Handle a vfr field in a config.
|
||||
|
||||
vm virtual machine
|
||||
config vm config
|
||||
val vfr field
|
||||
"""
|
||||
# Get the rules and add them.
|
||||
# (vfr (vif (id foo) (ip x.x.x.x)) ... )
|
||||
list = sxp.children(val, 'vif')
|
||||
ipaddrs = []
|
||||
for v in list:
|
||||
id = sxp.child_value(v, 'id')
|
||||
if id is None:
|
||||
raise VmError('vfr: missing vif id')
|
||||
id = int(id)
|
||||
dev = vm.get_device_by_index('vif', id)
|
||||
if not dev:
|
||||
raise VmError('vfr: invalid vif id %d' % id)
|
||||
vif = sxp.child_value(dev, 'vif')
|
||||
ip = sxp.child_value(v, 'ip')
|
||||
if not ip:
|
||||
raise VmError('vfr: missing ip address')
|
||||
ipaddrs.append(ip);
|
||||
# todo: Configure the ipaddrs.
|
||||
vm.ipaddrs = ipaddrs
|
||||
|
||||
def vnet_bridge(vnet, vmac, dom, idx):
|
||||
"""Add the device for the vif to the bridge for its vnet.
|
||||
"""
|
||||
vif = "vif%d.%d" % (dom, idx)
|
||||
try:
|
||||
cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
|
||||
log.debug("vnet_bridge> %s", cmd)
|
||||
out = file("/proc/vnet/policy", "wb")
|
||||
out.write(cmd)
|
||||
err = out.close()
|
||||
log.debug("vnet_bridge> err=%d", err)
|
||||
except IOError, ex:
|
||||
log.exception("vnet_bridge>")
|
||||
|
||||
def vm_field_vnet(vm, config, val, index):
|
||||
"""Handle a vnet field in a config.
|
||||
|
||||
vm virtual machine
|
||||
config vm config
|
||||
val vnet field
|
||||
index index
|
||||
"""
|
||||
# Get the vif children. For each vif look up the vif device
|
||||
# with the given id and configure its vnet.
|
||||
# (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
|
||||
vif_vnets = sxp.children(val, 'vif')
|
||||
for v in vif_vnets:
|
||||
id = sxp.child_value(v, 'id')
|
||||
if id is None:
|
||||
raise VmError('vnet: missing vif id')
|
||||
dev = vm.get_device_by_id('vif', id)
|
||||
#vnet = sxp.child_value(v, 'vnet', 1)
|
||||
#mac = sxp.child_value(dev, 'mac')
|
||||
#vif = sxp.child_value(dev, 'vif')
|
||||
#vnet_bridge(vnet, mac, vm.dom, 0)
|
||||
#vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
|
||||
|
||||
def vm_field_ignore(vm, config, val, index):
|
||||
"""Dummy config field handler used for fields with built-in handling.
|
||||
|
||||
@param vm: virtual machine
|
||||
@param config: vm config
|
||||
@param val: vfr field
|
||||
@param index: field index
|
||||
"""
|
||||
pass
|
||||
|
||||
# Register image handlers for linux and bsd.
|
||||
# Register image handlers.
|
||||
add_image_handler('linux', vm_image_linux)
|
||||
add_image_handler('netbsd', vm_image_netbsd)
|
||||
|
||||
# Register device handlers for vifs and vbds.
|
||||
# Register device handlers.
|
||||
add_device_handler('vif', vm_dev_vif)
|
||||
add_device_handler('vbd', vm_dev_vbd)
|
||||
add_device_handler('pci', vm_dev_pci)
|
||||
@@ -1098,6 +1126,4 @@ add_config_handler('image', vm_field_ignore)
|
||||
add_config_handler('device', vm_field_ignore)
|
||||
add_config_handler('backend', vm_field_ignore)
|
||||
|
||||
# Register config handlers for vfr and vnet.
|
||||
add_config_handler('vfr', vm_field_vfr)
|
||||
add_config_handler('vnet', vm_field_vnet)
|
||||
# Register other config handlers.
|
||||
@@ -22,9 +22,9 @@ class SrvDomain(SrvDir):
|
||||
|
||||
def op_configure(self, op, req):
|
||||
fn = FormFn(self.xd.domain_configure,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['config', 'sxpr']])
|
||||
deferred = fn(req.args, {'dom': self.dom.id})
|
||||
deferred = fn(req.args, {'dom': self.dom.name})
|
||||
deferred.addErrback(self._op_configure_err, req)
|
||||
return deferred
|
||||
|
||||
@@ -33,35 +33,35 @@ class SrvDomain(SrvDir):
|
||||
return str(err)
|
||||
|
||||
def op_unpause(self, op, req):
|
||||
val = self.xd.domain_unpause(self.dom.id)
|
||||
val = self.xd.domain_unpause(self.dom.name)
|
||||
return val
|
||||
|
||||
def op_pause(self, op, req):
|
||||
val = self.xd.domain_pause(self.dom.id)
|
||||
val = self.xd.domain_pause(self.dom.name)
|
||||
return val
|
||||
|
||||
def op_shutdown(self, op, req):
|
||||
fn = FormFn(self.xd.domain_shutdown,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['reason', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
req.setResponseCode(http.ACCEPTED)
|
||||
req.setHeader("Location", "%s/.." % req.prePathURL())
|
||||
return val
|
||||
|
||||
def op_destroy(self, op, req):
|
||||
fn = FormFn(self.xd.domain_destroy,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['reason', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
req.setHeader("Location", "%s/.." % req.prePathURL())
|
||||
return val
|
||||
|
||||
def op_save(self, op, req):
|
||||
fn = FormFn(self.xd.domain_save,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['file', 'str']])
|
||||
deferred = fn(req.args, {'dom': self.dom.id})
|
||||
deferred = fn(req.args, {'dom': self.dom.name})
|
||||
deferred.addCallback(self._op_save_cb, req)
|
||||
deferred.addErrback(self._op_save_err, req)
|
||||
return deferred
|
||||
@@ -75,9 +75,9 @@ class SrvDomain(SrvDir):
|
||||
|
||||
def op_migrate(self, op, req):
|
||||
fn = FormFn(self.xd.domain_migrate,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['destination', 'str']])
|
||||
deferred = fn(req.args, {'dom': self.dom.id})
|
||||
deferred = fn(req.args, {'dom': self.dom.name})
|
||||
print 'op_migrate>', deferred
|
||||
deferred.addCallback(self._op_migrate_cb, req)
|
||||
deferred.addErrback(self._op_migrate_err, req)
|
||||
@@ -99,99 +99,85 @@ class SrvDomain(SrvDir):
|
||||
req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
|
||||
return str(err)
|
||||
|
||||
def op_device_create(self, op, req):
|
||||
fn = FormFn(self.xd.domain_device_create,
|
||||
[['dom', 'int'],
|
||||
['config', 'sxpr']])
|
||||
d = fn(req.args, {'dom': self.dom.id})
|
||||
return d
|
||||
|
||||
def op_device_destroy(self, op, req):
|
||||
fn = FormFn(self.xd.domain_device_destroy,
|
||||
[['dom', 'int'],
|
||||
['type', 'str'],
|
||||
['index', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_pincpu(self, op, req):
|
||||
fn = FormFn(self.xd.domain_pincpu,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['cpu', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
return val
|
||||
|
||||
def op_cpu_bvt_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_cpu_bvt_set,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['mcuadv', 'int'],
|
||||
['warp', 'int'],
|
||||
['warpl', 'int'],
|
||||
['warpu', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
return val
|
||||
|
||||
def op_cpu_fbvt_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_cpu_fbvt_set,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['mcuadv', 'int'],
|
||||
['warp', 'int'],
|
||||
['warpl', 'int'],
|
||||
['warpu', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
return val
|
||||
|
||||
def op_cpu_atropos_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_cpu_atropos_set,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['period', 'int'],
|
||||
['slice', 'int'],
|
||||
['latency', 'int'],
|
||||
['xtratime', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
return val
|
||||
|
||||
def op_maxmem_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_maxmem_set,
|
||||
[['dom', 'int'],
|
||||
[['dom', 'str'],
|
||||
['memory', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
return val
|
||||
|
||||
def op_device_create(self, op, req):
|
||||
fn = FormFn(self.xd.domain_device_create,
|
||||
[['dom', 'str'],
|
||||
['config', 'sxpr']])
|
||||
d = fn(req.args, {'dom': self.dom.name})
|
||||
return d
|
||||
|
||||
def op_device_destroy(self, op, req):
|
||||
fn = FormFn(self.xd.domain_device_destroy,
|
||||
[['dom', 'str'],
|
||||
['type', 'str'],
|
||||
['idx', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
return val
|
||||
|
||||
def op_vifs(self, op, req):
|
||||
return self.xd.domain_vif_ls(self.dom.id)
|
||||
devs = self.xd.domain_vif_ls(self.dom.name)
|
||||
return [ dev.sxpr() for dev in devs ]
|
||||
|
||||
def op_vif(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vif_get,
|
||||
[['dom', 'int'],
|
||||
['vif', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
[['dom', 'str'],
|
||||
['vif', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
return val
|
||||
|
||||
def op_vbds(self, op, req):
|
||||
return self.xd.domain_vbd_ls(self.dom.id)
|
||||
devs = self.xd.domain_vbd_ls(self.dom.name)
|
||||
return [ dev.sxpr() for dev in devs ]
|
||||
|
||||
def op_vbd(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vbd_get,
|
||||
[['dom', 'int'],
|
||||
['vbd', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_vbd_add(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vbd_add,
|
||||
[['dom', 'int'],
|
||||
['uname', 'str'],
|
||||
['dev', 'str'],
|
||||
['mode', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_vbd_remove(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vbd_remove,
|
||||
[['dom', 'int'],
|
||||
['dev', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
[['dom', 'str'],
|
||||
['vbd', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.name})
|
||||
return val
|
||||
|
||||
def render_POST(self, req):
|
||||
|
||||
@@ -24,7 +24,7 @@ class SrvDomainDir(SrvDir):
|
||||
|
||||
def domain(self, x):
|
||||
val = None
|
||||
dom = self.xd.domain_get(x)
|
||||
dom = self.xd.domain_lookup(x)
|
||||
if not dom:
|
||||
raise XendError('No such domain ' + str(x))
|
||||
val = SrvDomain(dom)
|
||||
@@ -74,7 +74,7 @@ class SrvDomainDir(SrvDir):
|
||||
def _op_create_cb(self, dominfo, configstring, req):
|
||||
"""Callback to handle deferred domain creation.
|
||||
"""
|
||||
dom = dominfo.id
|
||||
dom = dominfo.name
|
||||
domurl = "%s/%s" % (req.prePathURL(), dom)
|
||||
req.setResponseCode(http.CREATED, "created")
|
||||
req.setHeader("Location", domurl)
|
||||
@@ -112,7 +112,7 @@ class SrvDomainDir(SrvDir):
|
||||
return deferred
|
||||
|
||||
def _op_restore_cb(self, dominfo, req):
|
||||
dom = dominfo.id
|
||||
dom = dominfo.name
|
||||
domurl = "%s/%s" % (req.prePathURL(), dom)
|
||||
req.setResponseCode(http.CREATED)
|
||||
req.setHeader("Location", domurl)
|
||||
@@ -159,12 +159,12 @@ class SrvDomainDir(SrvDir):
|
||||
sxp.show(domains, out=req)
|
||||
else:
|
||||
domains = self.xd.domains()
|
||||
domains.sort(lambda x, y: cmp(x.id, y.id))
|
||||
domains.sort(lambda x, y: cmp(x.name, y.name))
|
||||
req.write('<ul>')
|
||||
for d in domains:
|
||||
req.write('<li><a href="%s%s"> Domain %s</a>'
|
||||
% (url, d.id, d.id))
|
||||
req.write('name=%s' % d.name)
|
||||
% (url, d.name, d.name))
|
||||
req.write('id=%s' % d.id)
|
||||
req.write('memory=%d'% d.memory)
|
||||
req.write('</li>')
|
||||
req.write('</ul>')
|
||||
|
||||
@@ -215,7 +215,7 @@ class BlkDev(controller.Dev):
|
||||
"""
|
||||
|
||||
def __init__(self, ctrl, vdev, mode, segment):
|
||||
controller.Dev.__init__(self, ctrl)
|
||||
controller.Dev.__init__(self, segment['device'], ctrl)
|
||||
self.vdev = vdev
|
||||
self.mode = mode
|
||||
self.device = segment['device']
|
||||
@@ -227,7 +227,11 @@ class BlkDev(controller.Dev):
|
||||
return 'w' not in self.mode
|
||||
|
||||
def sxpr(self):
|
||||
val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ]
|
||||
val = ['blkdev',
|
||||
['idx', self.idx],
|
||||
['vdev', self.vdev],
|
||||
['device', self.device],
|
||||
['mode', self.mode]]
|
||||
return val
|
||||
|
||||
def destroy(self):
|
||||
|
||||
@@ -327,10 +327,14 @@ class Dev:
|
||||
"""Abstract class for a device attached to a device controller.
|
||||
"""
|
||||
|
||||
def __init__(self, controller):
|
||||
def __init__(self, idx, controller):
|
||||
self.idx = str(idx)
|
||||
self.controller = controller
|
||||
self.props = {}
|
||||
|
||||
def getidx(self):
|
||||
return self.idx
|
||||
|
||||
def setprop(self, k, v):
|
||||
self.props[k] = v
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ class NetDev(controller.Dev):
|
||||
"""
|
||||
|
||||
def __init__(self, ctrl, vif, config):
|
||||
controller.Dev.__init__(self, ctrl)
|
||||
controller.Dev.__init__(self, vif, ctrl)
|
||||
self.vif = vif
|
||||
self.evtchn = None
|
||||
self.configure(config)
|
||||
@@ -140,7 +140,10 @@ class NetDev(controller.Dev):
|
||||
def sxpr(self):
|
||||
vif = str(self.vif)
|
||||
mac = self.get_mac()
|
||||
val = ['vif', ['idx', vif], ['mac', mac]]
|
||||
val = ['vif',
|
||||
['idx', self.idx],
|
||||
['vif', vif],
|
||||
['mac', mac]]
|
||||
if self.bridge:
|
||||
val.append(['bridge', self.bridge])
|
||||
if self.script:
|
||||
|
||||
@@ -366,10 +366,11 @@ def show(sxpr, out=sys.stdout):
|
||||
show(x, out)
|
||||
i += 1
|
||||
out.write(k_list_close)
|
||||
elif isinstance(sxpr, (types.IntType, types.FloatType)):
|
||||
out.write(str(sxpr))
|
||||
elif isinstance(sxpr, types.StringType) and atomp(sxpr):
|
||||
out.write(sxpr)
|
||||
else:
|
||||
#out.write("'" + str(sxpr) + "'")
|
||||
out.write(repr(str(sxpr)))
|
||||
|
||||
def show_xml(sxpr, out=sys.stdout):
|
||||
|
||||
@@ -402,7 +402,7 @@ def make_domain(opts, config):
|
||||
except XendError, ex:
|
||||
opts.err(str(ex))
|
||||
|
||||
dom = int(sxp.child_value(dominfo, 'id'))
|
||||
dom = sxp.child_value(dominfo, 'name')
|
||||
console_info = sxp.child(dominfo, 'console')
|
||||
if console_info:
|
||||
console_port = int(sxp.child_value(console_info, 'console_port'))
|
||||
@@ -411,8 +411,8 @@ def make_domain(opts, config):
|
||||
|
||||
if server.xend_domain_unpause(dom) < 0:
|
||||
server.xend_domain_destroy(dom)
|
||||
opts.err("Failed to unpause domain %d" % dom)
|
||||
opts.info("Started domain %d, console on port %d"
|
||||
opts.err("Failed to unpause domain %s" % dom)
|
||||
opts.info("Started domain %s, console on port %d"
|
||||
% (dom, console_port))
|
||||
return (dom, console_port)
|
||||
|
||||
|
||||
@@ -27,14 +27,10 @@ def main(argv):
|
||||
return
|
||||
if len(args) < 1: opts.err('Missing domain')
|
||||
dom = args[0]
|
||||
try:
|
||||
domid = int(dom)
|
||||
except:
|
||||
opts.err('Invalid domain: ' + dom)
|
||||
if opts.vals.reboot:
|
||||
mode = 'reboot'
|
||||
else:
|
||||
mode = 'halt'
|
||||
server.xend_domain_destroy(domid, mode)
|
||||
server.xend_domain_destroy(dom, mode)
|
||||
|
||||
|
||||
@@ -246,10 +246,10 @@ class ProgList(Prog):
|
||||
use_long = 1
|
||||
|
||||
if n == 0:
|
||||
doms = map(int, server.xend_domains())
|
||||
doms = server.xend_domains()
|
||||
doms.sort()
|
||||
else:
|
||||
doms = map(int, params)
|
||||
doms = params
|
||||
|
||||
if use_long:
|
||||
self.long_list(doms)
|
||||
@@ -257,22 +257,27 @@ class ProgList(Prog):
|
||||
self.brief_list(doms)
|
||||
|
||||
def brief_list(self, doms):
|
||||
print 'Dom Name Mem(MB) CPU State Time(s)'
|
||||
print 'Name Id Mem(MB) CPU State Time(s) Console'
|
||||
for dom in doms:
|
||||
info = server.xend_domain(dom)
|
||||
d = {}
|
||||
d['dom'] = int(dom)
|
||||
d['dom'] = int(sxp.child_value(info, 'id', '-1'))
|
||||
d['name'] = sxp.child_value(info, 'name', '??')
|
||||
d['mem'] = int(sxp.child_value(info, 'memory', '0'))
|
||||
d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
|
||||
d['state'] = sxp.child_value(info, 'state', '??')
|
||||
d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
|
||||
print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)7.1f" % d)
|
||||
console = sxp.child(info, 'console')
|
||||
if console:
|
||||
d['port'] = sxp.child_value(console, 'console_port')
|
||||
else:
|
||||
d['port'] = ''
|
||||
print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3d %(state)5s %(cpu_time)7.1f %(port)4s"
|
||||
% d)
|
||||
|
||||
def long_list(self, doms):
|
||||
for dom in doms:
|
||||
info = server.xend_domain(dom)
|
||||
print '\nDomain %d' % dom
|
||||
PrettyPrint.prettyprint(info)
|
||||
|
||||
xm.prog(ProgList)
|
||||
|
||||
@@ -9,6 +9,8 @@ import time
|
||||
from xen.xend.XendClient import server
|
||||
from xen.xm.opts import *
|
||||
|
||||
DOM0 = 'Domain-0'
|
||||
|
||||
gopts = Opts(use="""[options] [DOM]
|
||||
|
||||
Shutdown one or more domains gracefully.
|
||||
@@ -35,11 +37,9 @@ gopts.opt('reboot', short='R',
|
||||
use='Shutdown and reboot.')
|
||||
|
||||
def shutdown(opts, doms, mode, wait):
|
||||
def domains():
|
||||
return [ int(a) for a in server.xend_domains() ]
|
||||
if doms == None: doms = domains()
|
||||
if 0 in doms:
|
||||
doms.remove(0)
|
||||
if doms == None: doms = server.xend_domains()
|
||||
if DOM0 in doms:
|
||||
doms.remove(DOM0)
|
||||
for d in doms:
|
||||
server.xend_domain_shutdown(d, mode)
|
||||
if wait:
|
||||
@@ -50,7 +50,7 @@ def shutdown(opts, doms, mode, wait):
|
||||
if d in alive: continue
|
||||
dead.append(d)
|
||||
for d in dead:
|
||||
opts.info("Domain %d terminated" % d)
|
||||
opts.info("Domain %s terminated" % d)
|
||||
doms.remove(d)
|
||||
time.sleep(1)
|
||||
opts.info("All domains terminated")
|
||||
@@ -76,13 +76,8 @@ def main_all(opts, args):
|
||||
def main_dom(opts, args):
|
||||
if len(args) < 1: opts.err('Missing domain')
|
||||
dom = args[0]
|
||||
try:
|
||||
domid = int(dom)
|
||||
except:
|
||||
opts.err('Invalid domain: ' + dom)
|
||||
|
||||
mode = shutdown_mode(opts)
|
||||
shutdown(opts, [ domid ], mode, opts.vals.wait)
|
||||
shutdown(opts, [ dom ], mode, opts.vals.wait)
|
||||
|
||||
def main(argv):
|
||||
opts = gopts
|
||||
@@ -90,7 +85,6 @@ def main(argv):
|
||||
if opts.vals.help:
|
||||
opts.usage()
|
||||
return
|
||||
print 'shutdown.main>', len(args), args
|
||||
if opts.vals.all:
|
||||
main_all(opts, args)
|
||||
else:
|
||||
|
||||