mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
bitkeeper revision 1.1108.33.13 (410a4f615sv1r0U6d481Qr5KYOtvpQ)
Merge ssh://xenbk@gandalf.hpl.hp.com//var/bk/xeno-unstable.bk into labyrinth.cl.cam.ac.uk:/auto/anfs/scratch/labyrinth/iap10/xeno-clone/xeno.bk
This commit is contained in:
commit
83bf229e04
22 files changed
+974
-510
No files matched your search
@@ -9,6 +9,7 @@ The 'data-plane' is done separately. For example, consoles
|
||||
are accessed via sockets on xend, but the list of consoles
|
||||
is accessible via this API.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import httplib
|
||||
import types
|
||||
@@ -130,7 +131,6 @@ class XendRequest:
|
||||
class XendClientProtocol:
|
||||
"""Abstract class for xend clients.
|
||||
"""
|
||||
|
||||
def xendRequest(self, url, method, args=None):
|
||||
"""Make a request to xend.
|
||||
Implement in a subclass.
|
||||
@@ -176,6 +176,9 @@ class XendClientProtocol:
|
||||
"""Handle the data returned in response to the request.
|
||||
"""
|
||||
if data is None: return None
|
||||
type = self.getHeader('Content-Type')
|
||||
if type != sxp.mime_type:
|
||||
return data
|
||||
try:
|
||||
pin = sxp.Parser()
|
||||
pin.input(data);
|
||||
@@ -194,11 +197,22 @@ class XendClientProtocol:
|
||||
"""
|
||||
raise err
|
||||
|
||||
def getHeader(self, key):
|
||||
"""Get a header from the response.
|
||||
Case is ignored in the key.
|
||||
|
||||
@param key: header key
|
||||
@return: header
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
class SynchXendClientProtocol(XendClientProtocol):
|
||||
"""A synchronous xend client. This will make a request, wait for
|
||||
the reply and return the result.
|
||||
"""
|
||||
|
||||
resp = None
|
||||
|
||||
def xendRequest(self, url, method, args=None):
|
||||
"""Make a request to xend.
|
||||
|
||||
@@ -211,6 +225,7 @@ class SynchXendClientProtocol(XendClientProtocol):
|
||||
if DEBUG: conn.set_debuglevel(1)
|
||||
conn.request(method, url.fullpath(), self.request.data, self.request.headers)
|
||||
resp = conn.getresponse()
|
||||
self.resp = resp
|
||||
val = self.handleStatus(resp.version, resp.status, resp.reason)
|
||||
if val is None:
|
||||
data = None
|
||||
@@ -220,6 +235,10 @@ class SynchXendClientProtocol(XendClientProtocol):
|
||||
val = self.handleResponse(data)
|
||||
return val
|
||||
|
||||
def getHeader(self, key):
|
||||
return self.resp.getheader(key)
|
||||
|
||||
|
||||
class AsynchXendClient(http.HTTPClient):
|
||||
"""A subclass of twisted's HTTPClient to deal with a connection to xend.
|
||||
Makes the request when connected, and delegates handling responses etc.
|
||||
@@ -245,6 +264,9 @@ class AsynchXendClient(http.HTTPClient):
|
||||
def handleStatus(self, version, status, message):
|
||||
return self.protocol.handleStatus(version, status, message)
|
||||
|
||||
def handleHeader(self, key, val):
|
||||
return self.protocol.handleHeader(key, val)
|
||||
|
||||
def handleResponse(self, data):
|
||||
return self.protocol.handleResponse(data)
|
||||
|
||||
@@ -257,47 +279,7 @@ class AsynchXendClientProtocol(XendClientProtocol):
|
||||
"""
|
||||
def __init__(self):
|
||||
self.err = None
|
||||
|
||||
def xendRequest(self, url, method, args=None):
|
||||
"""Make a request to xend. The returned deferred is called when
|
||||
the result is available.
|
||||
|
||||
@param url: xend request url
|
||||
@param method: http method: POST or GET
|
||||
@param args: request arguments (dict)
|
||||
@return: deferred
|
||||
"""
|
||||
request = XendRequest(url, method, args)
|
||||
self.deferred = Deferred()
|
||||
clientCreator = ClientCreator(reactor, AsynchXendClient, self, request)
|
||||
clientCreator.connectTCP(url.host, url.port)
|
||||
return self.deferred
|
||||
|
||||
def callErrback(self, err):
|
||||
if not self.deferred.called:
|
||||
self.err = err
|
||||
self.deferred.errback(err)
|
||||
return err
|
||||
|
||||
def callCallback(self, val):
|
||||
if not self.deferred.called:
|
||||
self.deferred.callback(val)
|
||||
return val
|
||||
|
||||
def handleException(self, err):
|
||||
return self.callErrback(err)
|
||||
|
||||
def handleResponse(self, data):
|
||||
if self.err: return self.err
|
||||
val = XendClientProtocol.handleResponse(self, data)
|
||||
if isinstance(val, Exception):
|
||||
self.callErrback(val)
|
||||
else:
|
||||
self.callCallback(val)
|
||||
return val
|
||||
|
||||
def __init__(self):
|
||||
self.err = None
|
||||
self.headers = {}
|
||||
|
||||
def xendRequest(self, url, method, args=None):
|
||||
"""Make a request to xend. The returned deferred is called when
|
||||
@@ -328,6 +310,12 @@ class AsynchXendClientProtocol(XendClientProtocol):
|
||||
def handleException(self, err):
|
||||
return self.callErrback(err)
|
||||
|
||||
def handleHeader(self, key, val):
|
||||
self.headers[key.lower()] = val
|
||||
|
||||
def getHeader(self, key):
|
||||
return self.headers.get(key.lower())
|
||||
|
||||
def handleResponse(self, data):
|
||||
if self.err: return self.err
|
||||
val = XendClientProtocol.handleResponse(self, data)
|
||||
@@ -344,9 +332,15 @@ class Xend:
|
||||
"""Default location of the xend server."""
|
||||
SRV_DEFAULT = "localhost:8000"
|
||||
|
||||
"""Environment variable to set the location of xend."""
|
||||
SRV_VAR = "XEND"
|
||||
|
||||
"""Default path to the xend root on the server."""
|
||||
ROOT_DEFAULT = "/xend/"
|
||||
|
||||
"""Environment variable to set the xend root path."""
|
||||
ROOT_VAR = "XEND_ROOT"
|
||||
|
||||
def __init__(self, client=None, srv=None, root=None):
|
||||
"""Create a xend client interface.
|
||||
If the client protocol is not specified, the default
|
||||
@@ -361,14 +355,24 @@ class Xend:
|
||||
self.client = client
|
||||
self.bind(srv, root)
|
||||
|
||||
def default_server(self):
|
||||
"""Get the default location of the xend server.
|
||||
"""
|
||||
return os.getenv(self.SRV_VAR, self.SRV_DEFAULT)
|
||||
|
||||
def default_root(self):
|
||||
"""Get the default root path on the xend server.
|
||||
"""
|
||||
return os.getenv(self.ROOT_VAR, self.ROOT_DEFAULT)
|
||||
|
||||
def bind(self, srv=None, root=None):
|
||||
"""Bind to a given server.
|
||||
|
||||
@param srv: server location (host:port)
|
||||
@param root: xend root path on the server
|
||||
"""
|
||||
if srv is None: srv = self.SRV_DEFAULT
|
||||
if root is None: root = self.ROOT_DEFAULT
|
||||
if srv is None: srv = self.default_server()
|
||||
if root is None: root = self.default_root()
|
||||
if not root.endswith('/'): root += '/'
|
||||
(host, port) = srv.split(':', 1)
|
||||
self.url = URL(host=host, port=port, path=root)
|
||||
@@ -397,9 +401,6 @@ class Xend:
|
||||
def eventurl(self, id=''):
|
||||
return self.url.relative('event/' + str(id))
|
||||
|
||||
def dmesgurl(self, id=''):
|
||||
return self.url.relative('node/dmesg/' + str(id))
|
||||
|
||||
def xend(self):
|
||||
return self.xendGet(self.url)
|
||||
|
||||
@@ -408,14 +409,17 @@ class Xend:
|
||||
|
||||
def xend_node_shutdown(self):
|
||||
return self.xendPost(self.nodeurl(),
|
||||
{'op' : 'shutdown'})
|
||||
{'op' : 'shutdown'})
|
||||
|
||||
def xend_node_restart(self):
|
||||
return self.xendPost(self.nodeurl(),
|
||||
{'op' : 'reboot'})
|
||||
{'op' : 'reboot'})
|
||||
|
||||
def xend_node_dmesg(self):
|
||||
return self.xendGet(self.dmesgurl())
|
||||
return self.xendGet(self.nodeurl('dmesg'))
|
||||
|
||||
def xend_node_log(self):
|
||||
return self.xendGet(self.nodeurl('log'))
|
||||
|
||||
def xend_node_cpu_rrobin_slice_set(self, slice):
|
||||
return self.xendPost(self.nodeurl(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
"""Get dmesg output for this node.
|
||||
"""
|
||||
@@ -11,7 +11,7 @@ class XendDmesg:
|
||||
self.xc = xen.lowlevel.xc.new()
|
||||
|
||||
def info(self):
|
||||
return [ self.xc.readconsolering() ]
|
||||
return self.xc.readconsolering()
|
||||
|
||||
|
||||
def instance():
|
||||
|
||||
+195
-135
@@ -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,45 @@ 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)
|
||||
try:
|
||||
return xc.domain_unpause(dom=dominfo.dom)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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)
|
||||
try:
|
||||
return xc.domain_pause(dom=dominfo.dom)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
def domain_shutdown(self, id, reason='poweroff'):
|
||||
"""Shutdown domain (nicely).
|
||||
@@ -406,18 +445,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 +464,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 +475,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 +485,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 +545,6 @@ class XendDomain:
|
||||
|
||||
@param id: domain id
|
||||
"""
|
||||
id = str(id)
|
||||
if reason == 'halt':
|
||||
self.domain_restart_cancel(id)
|
||||
elif reason == 'reboot':
|
||||
@@ -522,9 +562,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 +576,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 +586,176 @@ class XendDomain:
|
||||
@param dom: domain
|
||||
@param cpu: cpu number
|
||||
"""
|
||||
dom = int(dom)
|
||||
return xc.domain_pincpu(dom, cpu)
|
||||
dominfo = self.domain_lookup(id)
|
||||
try:
|
||||
return xc.domain_pincpu(itn(dominfo.id), cpu)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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,
|
||||
warp=warp, warpl=warpl, warpu=warpu)
|
||||
dominfo = self.domain_lookup(id)
|
||||
try:
|
||||
return xc.bvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv,
|
||||
warp=warp, warpl=warpl, warpu=warpu)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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)
|
||||
try:
|
||||
return xc.bvtsched_domain_get(dominfo.dom)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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,
|
||||
warp=warp, warpl=warpl, warpu=warpu)
|
||||
dominfo = self.domain_lookup(id)
|
||||
try:
|
||||
return xc.fbvtsched_domain_set(dom=dominfo.dom, mcuadv=mcuadv,
|
||||
warp=warp, warpl=warpl, warpu=warpu)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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)
|
||||
try:
|
||||
return xc.fbvtsched_domain_get(dominfo.dom)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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)
|
||||
try:
|
||||
return xc.atropos_domain_set(dominfo.dom, period, slice, latency, xtratime)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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)
|
||||
try:
|
||||
return xc.atropos_domain_get(dominfo.dom)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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)
|
||||
try:
|
||||
return xc.shadow_control(dominfo.dom, op)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
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)
|
||||
try:
|
||||
return xc.domain_setmaxmem(dominfo.dom, maxmem_kb = maxmem)
|
||||
except Exception, ex:
|
||||
raise XendError(str(ex))
|
||||
|
||||
|
||||
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)
|
||||
|
||||
@@ -563,7 +622,10 @@ class XendDomainInfo:
|
||||
if chan:
|
||||
log.debug("Closing channel to domain %d", self.dom)
|
||||
chan.close()
|
||||
return xc.domain_destroy(dom=self.dom)
|
||||
try:
|
||||
return xc.domain_destroy(dom=self.dom)
|
||||
except Exception, err:
|
||||
log.exception("Domain destroy failed: ", self.name)
|
||||
|
||||
def cleanup(self):
|
||||
"""Cleanup vm resources: release devices.
|
||||
@@ -661,11 +723,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 +747,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 +792,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 +812,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 +835,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 +858,8 @@ 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
|
||||
self.restart_cancel()
|
||||
msg = 'VM %s restarting too fast' % self.name
|
||||
log.error(msg)
|
||||
raise VmError(msg)
|
||||
self.restart_time = tnow
|
||||
@@ -830,17 +908,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 +938,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 +960,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 +984,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 +1010,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 +1033,13 @@ 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
|
||||
uname = sxp.child_value(val, 'uname')
|
||||
if not uname:
|
||||
raise VmError('vbd: Missing uname')
|
||||
@@ -971,13 +1050,16 @@ def vm_dev_vbd(vm, val, index):
|
||||
log.debug("Creating vbd dom=%d uname=%s dev=%s", vm.dom, uname, dev)
|
||||
defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
|
||||
def fn(vbd):
|
||||
dev = xend.blkif_dev(vm.dom, vdev)
|
||||
vm.add_device('vbd', dev)
|
||||
vbd.dev = dev
|
||||
vbd.uname = uname
|
||||
vm.add_device('vbd', vbd)
|
||||
return vbd
|
||||
defer.addCallback(fn)
|
||||
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 +1070,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 +1102,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 +1130,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.
|
||||
@@ -44,6 +44,7 @@ class XendLogging:
|
||||
mode='a',
|
||||
maxBytes=self.maxBytes,
|
||||
backupCount=self.backupCount)
|
||||
self.logfilename = filename
|
||||
self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat))
|
||||
log = self.getLogger()
|
||||
log.addHandler(self.logfile)
|
||||
@@ -51,6 +52,9 @@ class XendLogging:
|
||||
def getLogFile(self):
|
||||
return self.logfile
|
||||
|
||||
def getLogFilename(self):
|
||||
return self.logfilename
|
||||
|
||||
def initLogStderr(self):
|
||||
self.logstderr = StreamHandler()
|
||||
self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat))
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
import os
|
||||
from SrvDir import SrvDir
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendDmesg
|
||||
|
||||
from SrvDir import SrvDir
|
||||
|
||||
class SrvDmesg(SrvDir):
|
||||
"""Xen Dmesg output.
|
||||
"""
|
||||
@@ -16,13 +18,13 @@ class SrvDmesg(SrvDir):
|
||||
def render_GET(self, req):
|
||||
try:
|
||||
if self.use_sxp(req):
|
||||
req.setHeader("Content-Type", sxp.mime_type)
|
||||
sxp.show(['dmesg'] + self.info(), out=req)
|
||||
req.setHeader("Content-Type", "text/plain")
|
||||
req.write(self.info())
|
||||
else:
|
||||
req.write('<html><head></head><body>')
|
||||
req.write('<pre>')
|
||||
self.print_path(req)
|
||||
req.write(self.info()[0])
|
||||
req.write('<pre>')
|
||||
req.write(self.info())
|
||||
req.write('</pre></body></html>')
|
||||
return ''
|
||||
except Exception, ex:
|
||||
|
||||
@@ -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>')
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
import os
|
||||
|
||||
from SrvDir import SrvDir
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendNode
|
||||
@@ -14,6 +15,7 @@ class SrvNode(SrvDir):
|
||||
SrvDir.__init__(self)
|
||||
self.xn = XendNode.instance()
|
||||
self.add('dmesg', 'SrvDmesg')
|
||||
self.add('log', 'SrvXendLog')
|
||||
|
||||
def op_shutdown(self, op, req):
|
||||
val = self.xn.shutdown()
|
||||
@@ -58,7 +60,8 @@ class SrvNode(SrvDir):
|
||||
req.write('<ul>')
|
||||
for d in self.info():
|
||||
req.write('<li> %10s: %s' % (d[0], str(d[1])))
|
||||
req.write('<li><a href="' + url + 'dmesg">Xen dmesg output</a>')
|
||||
req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url)
|
||||
req.write('<li><a href="%slog>Xend log</a>' % url)
|
||||
req.write('</ul>')
|
||||
req.write('</body></html>')
|
||||
return ''
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
from twisted.web import static
|
||||
|
||||
from xen.xend import XendRoot
|
||||
|
||||
from SrvDir import SrvDir
|
||||
|
||||
class SrvXendLog(SrvDir):
|
||||
"""Xend log.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
SrvDir.__init__(self)
|
||||
logging = XendRoot.instance().get_logging()
|
||||
self.logfile = static.File(logging.getLogFilename(), defaultType="text/plain")
|
||||
self.logfile.type = "text/plain"
|
||||
self.logfile.encoding = None
|
||||
|
||||
def render_GET(self, req):
|
||||
try:
|
||||
return self.logfile.render(req)
|
||||
except Exception, ex:
|
||||
self._perform_err(ex, req)
|
||||
@@ -160,13 +160,15 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
else:
|
||||
pass
|
||||
|
||||
def respond_be_vbd_create(self, msg, d):
|
||||
def respond_be_vbd_create(self, msg, dev, d):
|
||||
"""Response handler for a be_vbd_create message.
|
||||
Tries to grow the vbd, and passes the deferred I{d} on for
|
||||
the grow to call.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@param dev: device
|
||||
@type dev: BlkDev
|
||||
@param d: deferred to call
|
||||
@type d: Deferred
|
||||
"""
|
||||
@@ -174,17 +176,19 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
blkif = self.getInstanceByDom(val['domid'])
|
||||
if blkif:
|
||||
d1 = defer.Deferred()
|
||||
d1.addCallback(self.respond_be_vbd_grow, d)
|
||||
d1.addCallback(self.respond_be_vbd_grow, dev, d)
|
||||
if d: d1.addErrback(d.errback)
|
||||
blkif.send_be_vbd_grow(val['vdevice'], response=d1)
|
||||
else:
|
||||
pass
|
||||
|
||||
def respond_be_vbd_grow(self, msg, d):
|
||||
def respond_be_vbd_grow(self, msg, dev, d):
|
||||
"""Response handler for a be_vbd_grow message.
|
||||
|
||||
@param msg: message
|
||||
@type msg: xu message
|
||||
@param dev: device
|
||||
@type dev: BlkDev
|
||||
@param d: deferred to call
|
||||
@type d: Deferred or None
|
||||
"""
|
||||
@@ -192,7 +196,7 @@ class BlkifControllerFactory(controller.ControllerFactory):
|
||||
# Check status?
|
||||
if self.attached:
|
||||
if d:
|
||||
d.callback(0)
|
||||
d.callback(dev)
|
||||
else:
|
||||
self.reattachDevice(val['domid'], val['vdevice'])
|
||||
|
||||
@@ -215,7 +219,9 @@ class BlkDev(controller.Dev):
|
||||
"""
|
||||
|
||||
def __init__(self, ctrl, vdev, mode, segment):
|
||||
controller.Dev.__init__(self, ctrl)
|
||||
controller.Dev.__init__(self, segment['device'], ctrl)
|
||||
self.dev = None
|
||||
self.uname = None
|
||||
self.vdev = vdev
|
||||
self.mode = mode
|
||||
self.device = segment['device']
|
||||
@@ -227,7 +233,15 @@ 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]]
|
||||
if self.dev:
|
||||
val.append(['dev', self.dev])
|
||||
if self.uname:
|
||||
val.append(['uname', self.uname])
|
||||
return val
|
||||
|
||||
def destroy(self):
|
||||
@@ -288,6 +302,7 @@ class BlkifController(controller.Controller):
|
||||
|
||||
def attachDevice(self, vdev, mode, segment, recreate=0):
|
||||
"""Attach a device to the specified interface.
|
||||
On success the returned deferred will be called with the device.
|
||||
|
||||
@param vdev: device index
|
||||
@type vdev: int
|
||||
@@ -304,10 +319,10 @@ class BlkifController(controller.Controller):
|
||||
if not dev: return -1
|
||||
d = defer.Deferred()
|
||||
if recreate:
|
||||
d.callback(self)
|
||||
d.callback(dev)
|
||||
else:
|
||||
d1 = defer.Deferred()
|
||||
d1.addCallback(self.factory.respond_be_vbd_create, d)
|
||||
d1.addCallback(self.factory.respond_be_vbd_create, dev, d)
|
||||
d1.addErrback(d.errback)
|
||||
self.send_be_vbd_create(vdev, response=d1)
|
||||
return d
|
||||
@@ -331,7 +346,7 @@ class BlkifController(controller.Controller):
|
||||
for dev in self.devices.values():
|
||||
dev.attached = 0
|
||||
d1 = defer.Deferred()
|
||||
d1.addCallback(self.factory.respond_be_vbd_create, None)
|
||||
d1.addCallback(self.factory.respond_be_vbd_create, None, None)
|
||||
self.send_be_vbd_create(vdev, response=d1)
|
||||
|
||||
def reattachDevice(self, vdev):
|
||||
|
||||
@@ -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)
|
||||
@@ -122,7 +122,7 @@ class NetDev(controller.Dev):
|
||||
self.mac = None
|
||||
self.bridge = None
|
||||
self.script = None
|
||||
self.ipaddr = None
|
||||
self.ipaddr = []
|
||||
|
||||
vmac = sxp.child_value(config, 'mac')
|
||||
if not vmac: raise XendError("invalid mac")
|
||||
@@ -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:
|
||||
@@ -161,7 +164,7 @@ class NetDev(controller.Dev):
|
||||
def get_mac(self):
|
||||
"""Get the MAC address as a string.
|
||||
"""
|
||||
return ':'.join(map(lambda x: "%x" % x, self.mac))
|
||||
return ':'.join(map(lambda x: "%02x" % x, self.mac))
|
||||
|
||||
def vifctl_params(self, vmname=None):
|
||||
dom = self.controller.dom
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
+237
-27
@@ -13,6 +13,39 @@ from xen.xend.XendClient import XendError, server
|
||||
from xen.xend.XendClient import main as xend_client_main
|
||||
from xen.xm import create, destroy, shutdown
|
||||
|
||||
class Group:
|
||||
|
||||
name = ""
|
||||
info = ""
|
||||
|
||||
def __init__(self, xm):
|
||||
self.xm = xm
|
||||
self.progs = {}
|
||||
|
||||
def addprog(self, prog):
|
||||
self.progs[prog.name] = prog
|
||||
|
||||
def getprog(self, name):
|
||||
return self.progs.get(name)
|
||||
|
||||
def proglist(self):
|
||||
kl = self.progs.keys()
|
||||
kl.sort()
|
||||
return [ self.getprog(k) for k in kl ]
|
||||
|
||||
def help(self, args):
|
||||
if self.info:
|
||||
print
|
||||
print self.info
|
||||
print
|
||||
else:
|
||||
print
|
||||
|
||||
def shortHelp(self, args):
|
||||
self.help(args)
|
||||
for p in self.proglist():
|
||||
p.shortHelp(args)
|
||||
|
||||
class Prog:
|
||||
"""Base class for sub-programs.
|
||||
"""
|
||||
@@ -61,6 +94,7 @@ class Xm:
|
||||
self.name = 'xm'
|
||||
self.unknown = ProgUnknown(self)
|
||||
self.progs = {}
|
||||
self.groups = {}
|
||||
|
||||
def err(self, msg):
|
||||
print >>sys.stderr, "Error:", msg
|
||||
@@ -101,6 +135,7 @@ class Xm:
|
||||
"""
|
||||
p = pklass(self)
|
||||
self.progs[p.name] = p
|
||||
self.getgroup(p.group).addprog(p)
|
||||
return p
|
||||
|
||||
def getprog(self, name, val=None):
|
||||
@@ -123,26 +158,71 @@ class Xm:
|
||||
|
||||
return self.progs.get(match, val)
|
||||
|
||||
def proglist(self):
|
||||
"""Get a list of sub-programs, ordered by group.
|
||||
"""
|
||||
groups = {}
|
||||
for p in self.progs.values():
|
||||
l = groups.get(p.group, [])
|
||||
l.append(p)
|
||||
groups[p.group] = l
|
||||
kl = groups.keys()
|
||||
def group(self, klass):
|
||||
g = klass(self)
|
||||
self.groups[g.name] = g
|
||||
return g
|
||||
|
||||
def getgroup(self, name):
|
||||
return self.groups[name]
|
||||
|
||||
def grouplist(self):
|
||||
kl = self.groups.keys()
|
||||
kl.sort()
|
||||
pl = []
|
||||
for k in kl:
|
||||
l = groups[k]
|
||||
l.sort()
|
||||
pl += l
|
||||
return pl
|
||||
return [ self.getgroup(k) for k in kl ]
|
||||
|
||||
# Create the application object, then add the sub-program classes.
|
||||
xm = Xm()
|
||||
|
||||
class GroupAll(Group):
|
||||
|
||||
name = "all"
|
||||
info = ""
|
||||
|
||||
xm.group(GroupAll)
|
||||
|
||||
class GroupDomain(Group):
|
||||
|
||||
name = "domain"
|
||||
info = "Commands on domains:"
|
||||
|
||||
xm.group(GroupDomain)
|
||||
|
||||
class GroupScheduler(Group):
|
||||
|
||||
name = "scheduler"
|
||||
info = "Comands controlling scheduling:"
|
||||
|
||||
xm.group(GroupScheduler)
|
||||
|
||||
class GroupHost(Group):
|
||||
|
||||
name = "host"
|
||||
info = "Commands related to the xen host (node):"
|
||||
|
||||
xm.group(GroupHost)
|
||||
|
||||
class GroupConsole(Group):
|
||||
|
||||
name = "console"
|
||||
info = "Commands related to consoles:"
|
||||
|
||||
xm.group(GroupConsole)
|
||||
|
||||
class GroupVbd(Group):
|
||||
|
||||
name = "vbd"
|
||||
info = "Commands related to virtual block devices:"
|
||||
|
||||
xm.group(GroupVbd)
|
||||
|
||||
class GroupVif(Group):
|
||||
|
||||
name = "vif"
|
||||
info = "Commands related to virtual network interfaces:"
|
||||
|
||||
xm.group(GroupVif)
|
||||
|
||||
class ProgHelp(Prog):
|
||||
|
||||
name = "help"
|
||||
@@ -157,8 +237,8 @@ class ProgHelp(Prog):
|
||||
else:
|
||||
print '%s: Unknown command: %s' % (self.name, name)
|
||||
else:
|
||||
for p in self.xm.proglist():
|
||||
p.shortHelp(args)
|
||||
for g in self.xm.grouplist():
|
||||
g.shortHelp(args)
|
||||
print "\nTry '%s help CMD' for help on CMD" % self.xm.name
|
||||
|
||||
main = help
|
||||
@@ -220,7 +300,7 @@ xm.prog(ProgRestore)
|
||||
class ProgList(Prog):
|
||||
group = 'domain'
|
||||
name = "list"
|
||||
info = """List info about domains."""
|
||||
info = """List information about domains."""
|
||||
|
||||
short_options = 'l'
|
||||
long_options = ['long']
|
||||
@@ -246,10 +326,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 +337,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)
|
||||
@@ -367,6 +452,40 @@ class ProgMaxmem(Prog):
|
||||
|
||||
xm.prog(ProgMaxmem)
|
||||
|
||||
class ProgDomid(Prog):
|
||||
group = 'domain'
|
||||
name = 'domid'
|
||||
info = 'Convert a domain name to a domain id.'
|
||||
|
||||
def help(self, args):
|
||||
print args[0], "DOM"
|
||||
print '\nGet the domain id for the domain with name DOM.'
|
||||
|
||||
def main (self, args):
|
||||
if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
|
||||
name = args[1]
|
||||
dom = server.xend_domain(name)
|
||||
print sxp.child_value(dom, 'id')
|
||||
|
||||
xm.prog(ProgDomid)
|
||||
|
||||
class ProgDomname(Prog):
|
||||
group = 'domain'
|
||||
name = 'domname'
|
||||
info = 'Convert a domain id to a domain name.'
|
||||
|
||||
def help(self, args):
|
||||
print args[0], "DOM"
|
||||
print '\nGet the name for the domain with id DOM.'
|
||||
|
||||
def main (self, args):
|
||||
if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
|
||||
name = args[1]
|
||||
dom = server.xend_domain(name)
|
||||
print sxp.child_value(dom, 'name')
|
||||
|
||||
xm.prog(ProgDomname)
|
||||
|
||||
class ProgBvt(Prog):
|
||||
group = 'scheduler'
|
||||
name = "bvt"
|
||||
@@ -507,7 +626,7 @@ class ProgConsole(Prog):
|
||||
info = """Open a console to a domain."""
|
||||
|
||||
def help(self, args):
|
||||
print "console DOM"
|
||||
print args[0], "DOM"
|
||||
print "\nOpen a console to domain DOM."
|
||||
|
||||
def main(self, args):
|
||||
@@ -528,7 +647,7 @@ class ProgCall(Prog):
|
||||
info = "Call xend api functions."
|
||||
|
||||
def help (self, args):
|
||||
print "call fn argss..."
|
||||
print args[0], "function args..."
|
||||
print """
|
||||
Call a xend HTTP API function. The leading 'xend_' on the function
|
||||
can be omitted. See xen.xend.XendClient for the API functions.
|
||||
@@ -545,9 +664,100 @@ class ProgDmesg(Prog):
|
||||
info = """Print Xen boot output."""
|
||||
|
||||
def main(self, args):
|
||||
print server.xend_node_dmesg()[1]
|
||||
print server.xend_node_dmesg()
|
||||
|
||||
xm.prog(ProgDmesg)
|
||||
|
||||
class ProgLog(Prog):
|
||||
group = 'host'
|
||||
name = "log"
|
||||
info = """Print the xend log."""
|
||||
|
||||
def main(self, args):
|
||||
print server.xend_node_log()
|
||||
|
||||
xm.prog(ProgLog)
|
||||
|
||||
class ProgVifList(Prog):
|
||||
group = 'vif'
|
||||
name = 'vif-list'
|
||||
info = """List virtual network interfaces for a domain."""
|
||||
|
||||
def help(self, args):
|
||||
print args[0], "DOM"
|
||||
print "\nList virtual network interfaces for domain DOM"
|
||||
|
||||
def main(self, args):
|
||||
if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
|
||||
dom = args[1]
|
||||
for x in server.xend_domain_vifs(dom):
|
||||
sxp.show(x)
|
||||
print
|
||||
|
||||
xm.prog(ProgVifList)
|
||||
|
||||
class ProgVbdList(Prog):
|
||||
group = 'vbd'
|
||||
name = 'vbd-list'
|
||||
info = """List virtual block devices for a domain."""
|
||||
|
||||
def help(self, args):
|
||||
print args[0], "DOM"
|
||||
print "\nList virtual block devices for domain DOM"
|
||||
|
||||
def main(self, args):
|
||||
if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
|
||||
dom = args[1]
|
||||
for x in server.xend_domain_vbds(dom):
|
||||
sxp.show(x)
|
||||
print
|
||||
|
||||
xm.prog(ProgVbdList)
|
||||
|
||||
class ProgVbdCreate(Prog):
|
||||
group = 'vbd'
|
||||
name = 'vbd-create'
|
||||
info = """Create a new virtual block device for a domain"""
|
||||
|
||||
def help(self, args):
|
||||
print args[0], "DOM UNAME DEV MODE"
|
||||
print """
|
||||
Create a virtual block device for a domain.
|
||||
|
||||
UNAME - device to export, e.g. phys:hda2
|
||||
DEV - device name in the domain, e.g. xda1
|
||||
MODE - access mode: r for read, w for read-write
|
||||
"""
|
||||
|
||||
def main(self, args):
|
||||
if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
|
||||
dom = args[1]
|
||||
vbd = ['vbd',
|
||||
['uname', args[2]],
|
||||
['dev', args[3]],
|
||||
['mode', args[4]]]
|
||||
server.xend_domain_device_create(dom, vbd)
|
||||
|
||||
xm.prog(ProgVbdCreate)
|
||||
|
||||
class ProgVbdDestroy(Prog):
|
||||
group = 'vbd'
|
||||
name = 'vbd-destroy'
|
||||
info = """Destroy a domain's virtual block device"""
|
||||
|
||||
def help(self, args):
|
||||
print args[0], "DOM DEV"
|
||||
print """
|
||||
Destroy vbd DEV attached to domain DOM. Detaches the device
|
||||
from the domain, but does not destroy the device contents."""
|
||||
|
||||
def main(self, args):
|
||||
if len(args!=3): self.err("%s: Invalid argument(s)" % args[0])
|
||||
dom = args[1]
|
||||
dev = args[2]
|
||||
sever.xend_domain_device_destroy(dom, "vbd", dev)
|
||||
|
||||
xm.prog(ProgVbdDestroy)
|
||||
|
||||
def main(args):
|
||||
xm.main(args)
|
||||
@@ -9,6 +9,9 @@ import time
|
||||
from xen.xend.XendClient import server
|
||||
from xen.xm.opts import *
|
||||
|
||||
DOM0_NAME = 'Domain-0'
|
||||
DOM0_ID = '0'
|
||||
|
||||
gopts = Opts(use="""[options] [DOM]
|
||||
|
||||
Shutdown one or more domains gracefully.
|
||||
@@ -35,11 +38,10 @@ 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()
|
||||
for x in [DOM0_NAME, DOM0_ID]:
|
||||
if x in doms:
|
||||
doms.remove(x)
|
||||
for d in doms:
|
||||
server.xend_domain_shutdown(d, mode)
|
||||
if wait:
|
||||
@@ -50,7 +52,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 +78,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 +87,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:
|
||||
|
||||