mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
bitkeeper revision 1.1327.2.9 (426f9bfcIjY9QAFCPqWBbFw35vclow)
Add support for unix-domain sockets on xend. Remove some dead code. Signed-off-by: Mike Wray <mike.wray@hp.com>
This commit is contained in:
1 parent
890ea518d9
commit
084b3e366e
33 files changed
+337
-723
No files matched your search
@@ -12,7 +12,6 @@ from xen.xend.XendLogging import log
|
||||
import resource
|
||||
import http
|
||||
import httpserver
|
||||
import defer
|
||||
|
||||
def uri_pathlist(p):
|
||||
"""Split a path into a list.
|
||||
|
||||
@@ -20,7 +20,7 @@ class SrvConstructor:
|
||||
|
||||
def __init__(self, klass):
|
||||
"""Create a constructor. It is assumed that the class
|
||||
should be imported as 'import klass from klass'.
|
||||
should be imported as 'from xen.xend.server.klass import klass'.
|
||||
|
||||
klass name of its class
|
||||
"""
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
class Deferred:
|
||||
pass
|
||||
@@ -4,6 +4,8 @@ import string
|
||||
import socket
|
||||
import types
|
||||
from urllib import quote, unquote
|
||||
import os
|
||||
import os.path
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend.Args import ArgError
|
||||
@@ -184,7 +186,9 @@ class HttpServerRequest(http.HttpRequest):
|
||||
|
||||
@param val: the value
|
||||
"""
|
||||
if isinstance(val, ThreadRequest):
|
||||
if val is None:
|
||||
return val
|
||||
elif isinstance(val, ThreadRequest):
|
||||
return val
|
||||
elif self.useSxp():
|
||||
self.setHeader("Content-Type", sxp.mime_type)
|
||||
@@ -316,18 +320,23 @@ class HttpServer:
|
||||
def getResource(self, req):
|
||||
return self.root.getRequestResource(req)
|
||||
|
||||
class UnixHttpServer(HttpServer):
|
||||
|
||||
def main():
|
||||
root = SrvDir()
|
||||
a = root.add("a", SrvDir())
|
||||
b = root.add("b", SrvDir())
|
||||
server = HttpServer(root=root)
|
||||
server.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
def __init__(self, path=None, root=None):
|
||||
HttpServer.__init__(self, interface='localhost', root=root)
|
||||
self.path = path
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def bind(self):
|
||||
pathdir = os.path.dirname(self.path)
|
||||
if not os.path.exists(pathdir):
|
||||
os.makedirs(pathdir)
|
||||
else:
|
||||
try:
|
||||
os.unlink(self.path)
|
||||
except SystemExit:
|
||||
raise
|
||||
except Exception, ex:
|
||||
pass
|
||||
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
#self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.socket.bind(self.path)
|
||||
@@ -24,7 +24,7 @@ class File(Resource):
|
||||
if self.type:
|
||||
req.setHeader('Content-Type', self.type)
|
||||
if self.encoding:
|
||||
rew.setHeader('Content-Encoding', self.encoding)
|
||||
req.setHeader('Content-Encoding', self.encoding)
|
||||
req.setHeader('Content-Length', self.getFileSize())
|
||||
try:
|
||||
io = file(self.filename, "r")
|
||||
@@ -40,7 +40,6 @@ class File(Resource):
|
||||
io.close()
|
||||
except:
|
||||
pass
|
||||
return ''
|
||||
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
from twisted.protocols import http
|
||||
from twisted.internet.protocol import ClientCreator
|
||||
from twisted.internet.defer import Deferred
|
||||
from twisted.internet import reactor
|
||||
|
||||
from XendProtocol import XendClientProtocol, XendRequest
|
||||
|
||||
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.
|
||||
to its protocol (usually an AsynchXendClientProtocol instance).
|
||||
"""
|
||||
def __init__(self, protocol, request):
|
||||
self.protocol = protocol
|
||||
self.request = request
|
||||
|
||||
def connectionMade(self):
|
||||
request = self.request
|
||||
url = self.request.url
|
||||
self.sendCommand(request.method, url.fullpath())
|
||||
self.sendHeader('Host', url.location())
|
||||
for (k, v) in request.headers.items():
|
||||
self.sendHeader(k, v)
|
||||
if request.data:
|
||||
self.sendHeader('Content-Length', len(request.data))
|
||||
self.endHeaders()
|
||||
if request.data:
|
||||
self.transport.write(request.data)
|
||||
|
||||
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)
|
||||
|
||||
class AsynchXendClientProtocol(XendClientProtocol):
|
||||
"""An asynchronous xend client. Uses twisted to connect to xend
|
||||
and make the request. It does not block waiting for the result,
|
||||
but sets up a deferred that is called when the result becomes available.
|
||||
|
||||
Uses AsynchXendClient to manage the connection.
|
||||
"""
|
||||
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
|
||||
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 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)
|
||||
if isinstance(val, Exception):
|
||||
self.callErrback(val)
|
||||
else:
|
||||
self.callCallback(val)
|
||||
return val
|
||||
@@ -2,7 +2,7 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
"""Client API for the HTTP interface on xend.
|
||||
Callable as a script - see main().
|
||||
Supports synchronous or asynchronous connection to xend.
|
||||
Supports inet or unix connection to xend.
|
||||
|
||||
This API is the 'control-plane' for xend.
|
||||
The 'data-plane' is done separately. For example, consoles
|
||||
@@ -15,7 +15,9 @@ import types
|
||||
|
||||
import sxp
|
||||
import PrettyPrint
|
||||
from XendProtocol import XendClientProtocol, SynchXendClientProtocol, XendError
|
||||
from XendProtocol import HttpXendClientProtocol, \
|
||||
UnixXendClientProtocol, \
|
||||
XendError
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
@@ -32,15 +34,6 @@ def fileof(val):
|
||||
return val
|
||||
raise XendError('cannot convert value')
|
||||
|
||||
# todo: need to sort of what urls/paths are using for objects.
|
||||
# e.g. for domains at the moment return '0'.
|
||||
# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
|
||||
# As an arg, assume abs path is obj uri, otherwise just id.
|
||||
|
||||
# Function to convert to full url: Xend.uri(path), e.g.
|
||||
# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
|
||||
# And should accept urls for ids?
|
||||
|
||||
class URL:
|
||||
"""A URL.
|
||||
"""
|
||||
@@ -115,7 +108,7 @@ class Xend:
|
||||
@param root: xend root path on the server
|
||||
"""
|
||||
if client is None:
|
||||
client = SynchXendClientProtocol()
|
||||
client = HttpXendClientProtocol()
|
||||
self.client = client
|
||||
self.bind(srv, root)
|
||||
|
||||
@@ -162,9 +155,6 @@ class Xend:
|
||||
def vneturl(self, id=''):
|
||||
return self.url.relative('vnet/' + str(id))
|
||||
|
||||
def eventurl(self, id=''):
|
||||
return self.url.relative('event/' + str(id))
|
||||
|
||||
def xend(self):
|
||||
return self.xendGet(self.url)
|
||||
|
||||
@@ -262,34 +252,33 @@ class Xend:
|
||||
|
||||
def xend_domain_maxmem_set(self, id, memory):
|
||||
return self.xendPost(self.domainurl(id),
|
||||
{ 'op' : 'maxmem_set',
|
||||
'memory' : memory })
|
||||
{ 'op' : 'maxmem_set',
|
||||
'memory' : memory })
|
||||
|
||||
def xend_domain_mem_target_set(self, id, mem_target):
|
||||
val = self.xendPost(self.domainurl(id),
|
||||
{'op' : 'mem_target_set',
|
||||
'target' : mem_target })
|
||||
return val
|
||||
|
||||
def xend_domain_vif_limit(self, id, vif, credit, period):
|
||||
return self.xendPost(self.domainurl(id),
|
||||
{ 'op' : 'vif_credit_limit',
|
||||
{ 'op' : 'vif_limit_set',
|
||||
'vif' : vif,
|
||||
'credit' : credit,
|
||||
'period' : period })
|
||||
|
||||
def xend_domain_vifs(self, id):
|
||||
def xend_domain_devices(self, id, type):
|
||||
return self.xendGet(self.domainurl(id),
|
||||
{ 'op' : 'vifs' })
|
||||
{'op' : 'devices',
|
||||
'type' : type })
|
||||
|
||||
def xend_domain_vif(self, id, vif):
|
||||
def xend_domain_device(self, id, type, idx):
|
||||
return self.xendGet(self.domainurl(id),
|
||||
{ 'op' : 'vif',
|
||||
'vif' : vif })
|
||||
|
||||
def xend_domain_vbds(self, id):
|
||||
return self.xendGet(self.domainurl(id),
|
||||
{'op' : 'vbds'})
|
||||
|
||||
def xend_domain_vbd(self, id, vbd):
|
||||
return self.xendGet(self.domainurl(id),
|
||||
{'op' : 'vbd',
|
||||
'vbd' : vbd })
|
||||
|
||||
{'op' : 'device',
|
||||
'type' : type,
|
||||
'idx' : idx })
|
||||
|
||||
def xend_domain_device_create(self, id, config):
|
||||
return self.xendPost(self.domainurl(id),
|
||||
{'op' : 'device_create',
|
||||
@@ -338,63 +327,29 @@ class Xend:
|
||||
return self.xendPost(self.vneturl(id),
|
||||
{'op' : 'delete' })
|
||||
|
||||
def xend_event_inject(self, sxpr):
|
||||
val = self.xendPost(self.eventurl(),
|
||||
{'op' : 'inject',
|
||||
'event' : fileof(sxpr) })
|
||||
|
||||
def xend_domain_mem_target_set(self, id, mem_target):
|
||||
val = self.xendPost(self.domainurl(id),
|
||||
{'op' : 'mem_target_set',
|
||||
'target' : mem_target })
|
||||
return val
|
||||
|
||||
def getAsynchXendClientProtocol():
|
||||
"""Load AsynchXendClientProtocol on demand to avoid the cost.
|
||||
def getHttpServer(srv=None):
|
||||
"""Create and return a xend client.
|
||||
"""
|
||||
global AsynchXendClientProtocol
|
||||
try:
|
||||
AsynchXendClientProtocol
|
||||
except:
|
||||
from XendAsynchProtocol import AsynchXendClientProtocol
|
||||
return AsynchXendClientProtocol
|
||||
return Xend(srv=srv, client=XendClientProtocol())
|
||||
|
||||
def getAsynchServer():
|
||||
"""Load AsynchXendClientProtocol and create an asynch xend client.
|
||||
|
||||
@return asynch Xend
|
||||
def getUnixServer(srv=None):
|
||||
"""Create and return a unix-domain xend client.
|
||||
"""
|
||||
getAsynchXendClientProtocol()
|
||||
return Xend(AsynchXendClientProtocol())
|
||||
return Xend(client=UnixXendClientProtocol(srv))
|
||||
|
||||
def xendmain(srv, asynch, fn, args):
|
||||
if asynch:
|
||||
getAsynchXendClientProtocol()
|
||||
client = AsynchXendClientProtocol()
|
||||
def xendmain(srv, fn, args, unix=False):
|
||||
if unix:
|
||||
xend = getUnixServer(srv)
|
||||
else:
|
||||
client = None
|
||||
xend = Xend(srv=srv, client=client)
|
||||
xend = getHttpServer(srv)
|
||||
xend.rc = 0
|
||||
try:
|
||||
v = getattr(xend, fn)(*args)
|
||||
PrettyPrint.prettyprint(v)
|
||||
return 0
|
||||
except XendError, err:
|
||||
print 'ERROR:', err
|
||||
return 1
|
||||
if asynch:
|
||||
def cbok(val):
|
||||
PrettyPrint.prettyprint(val)
|
||||
reactor.stop()
|
||||
def cberr(err):
|
||||
print 'ERROR:', err
|
||||
xend.rc = 1
|
||||
reactor.stop()
|
||||
v.addCallback(cbok)
|
||||
v.addErrback(cberr)
|
||||
reactor.run()
|
||||
return xend.rc
|
||||
else:
|
||||
PrettyPrint.prettyprint(v)
|
||||
return 0
|
||||
|
||||
def main(argv):
|
||||
"""Call an API function:
|
||||
@@ -411,16 +366,16 @@ python XendClient.py domain 0
|
||||
"""
|
||||
global DEBUG
|
||||
from getopt import getopt
|
||||
short_options = 'x:ad'
|
||||
long_options = ['xend=', 'asynch', 'debug']
|
||||
short_options = 'x:au:d'
|
||||
long_options = ['xend=', 'unix=', 'debug']
|
||||
(options, args) = getopt(argv[1:], short_options, long_options)
|
||||
srv = None
|
||||
asynch = 0
|
||||
unix = 1
|
||||
for k, v in options:
|
||||
if k in ['-x', '--xend']:
|
||||
srv = v
|
||||
elif k in ['-a', '--asynch']:
|
||||
asynch = 1
|
||||
elif k in ['-u', '--unix']:
|
||||
unix = int(v)
|
||||
elif k in ['-d', '--debug']:
|
||||
DEBUG = 1
|
||||
if len(args):
|
||||
@@ -431,9 +386,9 @@ python XendClient.py domain 0
|
||||
args = []
|
||||
if not fn.startswith('xend'):
|
||||
fn = 'xend_' + fn
|
||||
sys.exit(xendmain(srv, asynch, fn, args))
|
||||
sys.exit(xendmain(srv, fn, args, unix=unix))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv)
|
||||
else:
|
||||
server = Xend()
|
||||
server = getUnixServer()
|
||||
@@ -778,7 +778,7 @@ class XendDomain:
|
||||
dominfo = self.domain_lookup(id)
|
||||
return dominfo.getDeviceByIndex(type, idx)
|
||||
|
||||
def domain_vif_credit_limit(self, id, vif, credit, period):
|
||||
def domain_vif_limit_set(self, id, vif, credit, period):
|
||||
"""Limit the vif's transmission rate
|
||||
"""
|
||||
dominfo = self.domain_lookup(id)
|
||||
@@ -787,40 +787,6 @@ class XendDomain:
|
||||
raise XendError("invalid vif")
|
||||
return dev.setCreditLimit(credit, period)
|
||||
|
||||
def domain_vif_ls(self, id):
|
||||
"""Get list of virtual network interface (vif) indexes for a domain.
|
||||
|
||||
@param id: domain
|
||||
@return: vif indexes
|
||||
"""
|
||||
return self.domain_devtype_ls(id, 'vif')
|
||||
|
||||
def domain_vif_get(self, id, vif):
|
||||
"""Get a virtual network interface (vif) from a domain.
|
||||
|
||||
@param id: domain
|
||||
@param vif: vif index
|
||||
@return: vif device object (or None)
|
||||
"""
|
||||
return self.domain_devtype_get(id, 'vif', vif)
|
||||
|
||||
def domain_vbd_ls(self, id):
|
||||
"""Get list of virtual block device (vbd) indexes for a domain.
|
||||
|
||||
@param id: domain
|
||||
@return: vbd indexes
|
||||
"""
|
||||
return self.domain_devtype_ls(id, 'vbd')
|
||||
|
||||
def domain_vbd_get(self, id, vbd):
|
||||
"""Get a virtual block device (vbd) from a domain.
|
||||
|
||||
@param id: domain
|
||||
@param vbd: vbd index
|
||||
@return: vbd device (or None)
|
||||
"""
|
||||
return self.domain_devtype_get(id, 'vbd', vbd)
|
||||
|
||||
def domain_shadow_control(self, id, op):
|
||||
"""Shadow page control.
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
"""Handler for persistent domain configs.
|
||||
|
||||
"""
|
||||
|
||||
import sxp
|
||||
import XendDB
|
||||
import XendDomain
|
||||
|
||||
__all__ = [ "XendDomainConfig" ]
|
||||
|
||||
class XendDomainConfig:
|
||||
|
||||
dbpath = 'config'
|
||||
|
||||
def __init__(self):
|
||||
self.db = XendDB.XendDB(self.dbpath)
|
||||
|
||||
def domain_config_ls(self, path):
|
||||
return self.db.ls(path)
|
||||
|
||||
def domain_config_create(self, path, sxpr):
|
||||
self.db.save(path, sxpr)
|
||||
pass
|
||||
|
||||
def domain_config_delete(self, path):
|
||||
self.db.delete(path)
|
||||
|
||||
def domain_config_instance(self, path):
|
||||
"""Create a domain from a config.
|
||||
"""
|
||||
config = self.db.fetch(path)
|
||||
xd = XendDomain.instance()
|
||||
newdom = xd.domain_create(config)
|
||||
return newdom
|
||||
|
||||
def instance():
|
||||
global inst
|
||||
try:
|
||||
inst
|
||||
except:
|
||||
inst = XendDomainConfig()
|
||||
return inst
|
||||
@@ -1,5 +1,6 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
import socket
|
||||
import httplib
|
||||
import types
|
||||
|
||||
@@ -122,12 +123,19 @@ class XendClientProtocol:
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
class SynchXendClientProtocol(XendClientProtocol):
|
||||
class HttpXendClientProtocol(XendClientProtocol):
|
||||
"""A synchronous xend client. This will make a request, wait for
|
||||
the reply and return the result.
|
||||
"""
|
||||
|
||||
resp = None
|
||||
request = None
|
||||
|
||||
def makeConnection(self, url):
|
||||
return httplib.HTTPConnection(url.location())
|
||||
|
||||
def makeRequest(self, url, method, args):
|
||||
return XendRequest(url, method, args)
|
||||
|
||||
def xendRequest(self, url, method, args=None):
|
||||
"""Make a request to xend.
|
||||
@@ -136,8 +144,8 @@ class SynchXendClientProtocol(XendClientProtocol):
|
||||
@param method: http method: POST or GET
|
||||
@param args: request arguments (dict)
|
||||
"""
|
||||
self.request = XendRequest(url, method, args)
|
||||
conn = httplib.HTTPConnection(url.location())
|
||||
self.request = self.makeRequest(url, method, args)
|
||||
conn = self.makeConnection(url)
|
||||
if DEBUG: conn.set_debuglevel(1)
|
||||
conn.request(method, url.fullpath(), self.request.data, self.request.headers)
|
||||
resp = conn.getresponse()
|
||||
@@ -154,3 +162,29 @@ class SynchXendClientProtocol(XendClientProtocol):
|
||||
def getHeader(self, key):
|
||||
return self.resp.getheader(key)
|
||||
|
||||
class UnixConnection(httplib.HTTPConnection):
|
||||
"""Subclass of Python library HTTPConnection that uses a unix-domain socket.
|
||||
"""
|
||||
|
||||
def __init__(self, path):
|
||||
httplib.HTTPConnection.__init__(self, 'localhost')
|
||||
self.path = path
|
||||
|
||||
def connect(self):
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
sock.connect(self.path)
|
||||
self.sock = sock
|
||||
|
||||
class UnixXendClientProtocol(HttpXendClientProtocol):
|
||||
"""A synchronous xend client using a unix-domain socket.
|
||||
"""
|
||||
|
||||
XEND_PATH_DEFAULT = '/var/lib/xend/xend-socket'
|
||||
|
||||
def __init__(self, path=None):
|
||||
if path is None:
|
||||
path = self.XEND_PATH_DEFAULT
|
||||
self.path = path
|
||||
|
||||
def makeConnection(self, url):
|
||||
return UnixConnection(self.path)
|
||||
@@ -15,6 +15,7 @@ import sys
|
||||
|
||||
import EventServer
|
||||
from XendLogging import XendLogging
|
||||
from XendError import XendError
|
||||
|
||||
# Initial create of the event server.
|
||||
eserver = EventServer.instance()
|
||||
@@ -44,6 +45,9 @@ class XendRoot:
|
||||
|
||||
loglevel_default = 'DEBUG'
|
||||
|
||||
"""Default for the flag indicating whether xend should run an http server."""
|
||||
xend_http_server_default = 'no'
|
||||
|
||||
"""Default interface address xend listens at. """
|
||||
xend_address_default = ''
|
||||
|
||||
@@ -53,7 +57,13 @@ class XendRoot:
|
||||
"""Default port xend serves events at. """
|
||||
xend_event_port_default = '8001'
|
||||
|
||||
"""Default inteface address xend listens at for consoles."""
|
||||
"""Default for the flag indicating whether xend should run a unix-domain server."""
|
||||
xend_unix_server_default = 'yes'
|
||||
|
||||
"""Default path the unix-domain server listens at."""
|
||||
xend_unix_path_default = '/var/lib/xend/xend-socket'
|
||||
|
||||
"""Default interface address xend listens at for consoles."""
|
||||
console_address_default = ''
|
||||
|
||||
"""Default port xend serves consoles at. """
|
||||
@@ -157,6 +167,7 @@ class XendRoot:
|
||||
logfile = self.get_config_value("logfile", self.logfile_default)
|
||||
loglevel = self.get_config_value("loglevel", self.loglevel_default)
|
||||
self.logging = XendLogging(logfile, level=loglevel)
|
||||
self.logging.addLogStderr()
|
||||
|
||||
def get_logging(self):
|
||||
"""Get the XendLogging instance.
|
||||
@@ -218,15 +229,35 @@ class XendRoot:
|
||||
"""
|
||||
return sxp.child_value(self.config, name, val=val)
|
||||
|
||||
def get_config_bool(self, name, val=None):
|
||||
v = self.get_config_value(name, val)
|
||||
if v in ['yes', '1', 'on', 1, True]:
|
||||
return True
|
||||
if v in ['no', '0', 'off', 0, False]:
|
||||
return False
|
||||
raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
|
||||
|
||||
def get_config_int(self, name, val=None):
|
||||
v = self.get_config_value(name, val)
|
||||
try:
|
||||
return int(v)
|
||||
except Exception, ex:
|
||||
raise XendError("invalid xend config %s: expected int: %s" % (name, v))
|
||||
|
||||
def get_xend_http_server(self):
|
||||
"""Get the flag indicating whether xend should run an http server.
|
||||
"""
|
||||
return self.get_config_bool("xend-http-server", self.xend_http_server_default)
|
||||
|
||||
def get_xend_port(self):
|
||||
"""Get the port xend listens at for its HTTP interface.
|
||||
"""
|
||||
return int(self.get_config_value('xend-port', self.xend_port_default))
|
||||
return self.get_config_int('xend-port', self.xend_port_default)
|
||||
|
||||
def get_xend_event_port(self):
|
||||
"""Get the port xend listens at for connection to its event server.
|
||||
"""
|
||||
return int(self.get_config_value('xend-event-port', self.xend_event_port_default))
|
||||
return self.get_config_int('xend-event-port', self.xend_event_port_default)
|
||||
|
||||
def get_xend_address(self):
|
||||
"""Get the address xend listens at for its HTTP and event ports.
|
||||
@@ -236,6 +267,16 @@ class XendRoot:
|
||||
"""
|
||||
return self.get_config_value('xend-address', self.xend_address_default)
|
||||
|
||||
def get_xend_unix_server(self):
|
||||
"""Get the flag indicating whether xend should run a unix-domain server.
|
||||
"""
|
||||
return self.get_config_bool("xend-unix-server", self.xend_unix_server_default)
|
||||
|
||||
def get_xend_unix_path(self):
|
||||
"""Get the path the xend unix-domain server listens at.
|
||||
"""
|
||||
return self.get_config_value("xend-unix-path", self.xend_unix_path_default)
|
||||
|
||||
def get_console_address(self):
|
||||
"""Get the address xend listens at for its console ports.
|
||||
This defaults to the empty string which allows all hosts to connect.
|
||||
@@ -247,7 +288,7 @@ class XendRoot:
|
||||
def get_console_port_base(self):
|
||||
"""Get the base port number used to generate console ports for domains.
|
||||
"""
|
||||
return int(self.get_config_value('console-port-base', self.console_port_base_default))
|
||||
return self.get_config_int('console-port-base', self.console_port_base_default)
|
||||
|
||||
def get_block_script(self, type):
|
||||
return self.get_config_value('block-%s' % type, '')
|
||||
@@ -262,8 +303,7 @@ class XendRoot:
|
||||
return self.get_config_value('vif-script', 'vif-bridge')
|
||||
|
||||
def get_vif_antispoof(self):
|
||||
v = self.get_config_value('vif-antispoof', 'yes')
|
||||
return v in ['yes', '1', 'on']
|
||||
return self.get_config_bool('vif-antispoof', 'yes')
|
||||
|
||||
def instance():
|
||||
"""Get an instance of XendRoot.
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
from xen.web.SrvBase import *
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendConsole
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
|
||||
class SrvConsole(SrvDir):
|
||||
"""An individual console.
|
||||
|
||||
@@ -326,10 +326,10 @@ class Daemon:
|
||||
self.createFactories()
|
||||
self.listenEvent(xroot)
|
||||
self.listenChannels()
|
||||
serverthread = SrvServer.create(bridge=1)
|
||||
servers = SrvServer.create()
|
||||
self.daemonize()
|
||||
print 'running serverthread...'
|
||||
serverthread.start()
|
||||
servers.start()
|
||||
except Exception, ex:
|
||||
print >>sys.stderr, 'Exception starting xend:', ex
|
||||
if DEBUG:
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
from xen.web.SrvBase import *
|
||||
from xen.web.SrvDir import *
|
||||
@@ -5,7 +5,7 @@ import os
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendDmesg
|
||||
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
|
||||
class SrvDmesg(SrvDir):
|
||||
"""Xen Dmesg output.
|
||||
|
||||
@@ -8,7 +8,7 @@ from xen.xend import XendConsole
|
||||
from xen.xend import PrettyPrint
|
||||
from xen.xend.Args import FormFn
|
||||
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
|
||||
class SrvDomain(SrvDir):
|
||||
"""Service managing a single domain.
|
||||
@@ -35,10 +35,6 @@ class SrvDomain(SrvDir):
|
||||
return val
|
||||
|
||||
def op_pause(self, op, req):
|
||||
# Pause doesn't need a thread, but request one for testing.
|
||||
return req.threadRequest(self.do_pause, op, req)
|
||||
|
||||
def do_pause(self, op, req):
|
||||
val = self.xd.domain_pause(self.dom.name)
|
||||
return val
|
||||
|
||||
@@ -113,6 +109,31 @@ class SrvDomain(SrvDir):
|
||||
['memory', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_mem_target_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_mem_target_set,
|
||||
[['dom', 'str'],
|
||||
['target', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_devices(self, op, req):
|
||||
fn = FormFn(self.xd.domain_devtype_ls,
|
||||
[['dom', 'str'],
|
||||
['type', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_device(self, op, req):
|
||||
fn = FormFn(self.xd.domain_devtype_get,
|
||||
[['dom', 'str'],
|
||||
['type', 'str'],
|
||||
['idx', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
if val:
|
||||
return val.sxpr()
|
||||
else:
|
||||
raise XendError("invalid device")
|
||||
|
||||
def op_device_create(self, op, req):
|
||||
fn = FormFn(self.xd.domain_device_create,
|
||||
@@ -145,8 +166,8 @@ class SrvDomain(SrvDir):
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_vif_credit_limit(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vif_credit_limit,
|
||||
def op_vif_limit_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vif_limit_set,
|
||||
[['dom', 'str'],
|
||||
['vif', 'int'],
|
||||
['credit', 'int'],
|
||||
@@ -154,35 +175,6 @@ class SrvDomain(SrvDir):
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_vifs(self, op, req):
|
||||
devs = self.xd.domain_vif_ls(self.dom.id)
|
||||
return [ dev.sxpr() for dev in devs ]
|
||||
|
||||
def op_vif(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vif_get,
|
||||
[['dom', 'str'],
|
||||
['vif', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_vbds(self, op, req):
|
||||
devs = self.xd.domain_vbd_ls(self.dom.id)
|
||||
return [ dev.sxpr() for dev in devs ]
|
||||
|
||||
def op_vbd(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vbd_get,
|
||||
[['dom', 'str'],
|
||||
['vbd', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_mem_target_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_mem_target_set,
|
||||
[['dom', 'str'],
|
||||
['target', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def render_POST(self, req):
|
||||
return self.perform(req)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from xen.xend.Args import FormFn
|
||||
from xen.xend.XendError import XendError
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
from SrvDomain import SrvDomain
|
||||
|
||||
class SrvDomainDir(SrvDir):
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend import EventServer
|
||||
from SrvDir import SrvDir
|
||||
|
||||
class SrvEventDir(SrvDir):
|
||||
"""Event directory.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
SrvDir.__init__(self)
|
||||
self.eserver = EventServer.instance()
|
||||
|
||||
def op_inject(self, op, req):
|
||||
eventstring = req.args.get('event')
|
||||
pin = sxp.Parser()
|
||||
pin.input(eventstring)
|
||||
pin.input_eof()
|
||||
sxpr = pin.get_val()
|
||||
self.eserver.inject(sxp.name(sxpr), sxpr)
|
||||
if req.use_sxp:
|
||||
sxp.name(sxpr)
|
||||
else:
|
||||
return '<code>' + eventstring + '</code>'
|
||||
|
||||
def render_POST(self, req):
|
||||
return self.perform(req)
|
||||
|
||||
def form(self, req):
|
||||
action = req.prePathURL()
|
||||
req.write('<form method="post" action="%s" enctype="multipart/form-data">'
|
||||
% action)
|
||||
req.write('<button type="submit" name="op" value="inject">Inject</button>')
|
||||
req.write('Event <input type="text" name="event" size="40"><br>')
|
||||
req.write('</form>')
|
||||
req.write('<form method="post" action="%s" enctype="multipart/form-data">'
|
||||
% action)
|
||||
req.write('<button type="submit" name="op" value="inject">Inject</button>')
|
||||
req.write('Event file<input type="file" name="event"><br>')
|
||||
req.write('</form>')
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import os
|
||||
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendNode
|
||||
from xen.xend.Args import FormFn
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from xen.xend import XendRoot
|
||||
xroot = XendRoot.instance()
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
|
||||
class SrvRoot(SrvDir):
|
||||
"""The root of the xend server.
|
||||
@@ -16,7 +16,6 @@ class SrvRoot(SrvDir):
|
||||
('node', 'SrvNode' ),
|
||||
('domain', 'SrvDomainDir' ),
|
||||
('console', 'SrvConsoleDir' ),
|
||||
('event', 'SrvEventDir' ),
|
||||
('vnet', 'SrvVnetDir' ),
|
||||
]
|
||||
|
||||
|
||||
@@ -27,23 +27,38 @@
|
||||
|
||||
from threading import Thread
|
||||
|
||||
from xen.web.httpserver import HttpServer
|
||||
from xen.web.httpserver import HttpServer, UnixHttpServer
|
||||
|
||||
from xen.xend import XendRoot
|
||||
xroot = XendRoot.instance()
|
||||
from xen.xend import XendRoot; xroot = XendRoot.instance()
|
||||
from xen.xend import Vifctl
|
||||
from SrvRoot import SrvRoot
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
|
||||
def create(port=None, interface=None, bridge=0):
|
||||
if port is None:
|
||||
port = xroot.get_xend_port()
|
||||
if interface is None:
|
||||
interface = xroot.get_xend_address()
|
||||
if bridge:
|
||||
from SrvRoot import SrvRoot
|
||||
|
||||
class XendServers:
|
||||
|
||||
def __init__(self):
|
||||
self.servers = []
|
||||
|
||||
def add(self, server):
|
||||
self.servers.append(server)
|
||||
|
||||
def start(self):
|
||||
Vifctl.network('start')
|
||||
for server in self.servers:
|
||||
thread = Thread(target=server.run)
|
||||
thread.start()
|
||||
|
||||
def create():
|
||||
root = SrvDir()
|
||||
root.putChild('xend', SrvRoot())
|
||||
server = HttpServer(root=root, interface=interface, port=port)
|
||||
thread = Thread(name="XendHttpServer", target=server.run)
|
||||
return thread
|
||||
servers = XendServers()
|
||||
if xroot.get_xend_http_server():
|
||||
port = xroot.get_xend_port()
|
||||
interface = xroot.get_xend_address()
|
||||
servers.add(HttpServer(root=root, interface=interface, port=port))
|
||||
if xroot.get_xend_unix_server():
|
||||
path = xroot.get_xend_unix_path()
|
||||
print 'unix path=', path
|
||||
servers.add(UnixHttpServer(path=path, root=root))
|
||||
return servers
|
||||
@@ -1,239 +0,0 @@
|
||||
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
|
||||
from xen.web import http
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendDomain
|
||||
from xen.xend import XendConsole
|
||||
from xen.xend import PrettyPrint
|
||||
from xen.xend.Args import FormFn
|
||||
|
||||
from SrvDir import SrvDir
|
||||
|
||||
class SrvDomain(SrvDir):
|
||||
"""Service managing a single domain.
|
||||
"""
|
||||
|
||||
def __init__(self, dom):
|
||||
SrvDir.__init__(self)
|
||||
self.dom = dom
|
||||
self.xd = XendDomain.instance()
|
||||
self.xconsole = XendConsole.instance()
|
||||
|
||||
def op_configure(self, op, req):
|
||||
"""Configure an existing domain.
|
||||
Configure is unusual in that it requires a domain id,
|
||||
not a domain name.
|
||||
"""
|
||||
fn = FormFn(self.xd.domain_configure,
|
||||
[['dom', 'int'],
|
||||
['config', 'sxpr']])
|
||||
deferred = fn(req.args, {'dom': self.dom.dom})
|
||||
deferred.addErrback(self._op_configure_err, req)
|
||||
return deferred
|
||||
|
||||
def _op_configure_err(self, err, req):
|
||||
req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
|
||||
return str(err)
|
||||
|
||||
def op_unpause(self, op, req):
|
||||
val = self.xd.domain_unpause(self.dom.name)
|
||||
return val
|
||||
|
||||
def op_pause(self, op, req):
|
||||
val = self.xd.domain_pause(self.dom.name)
|
||||
return val
|
||||
|
||||
def op_shutdown(self, op, req):
|
||||
fn = FormFn(self.xd.domain_shutdown,
|
||||
[['dom', 'str'],
|
||||
['reason', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
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', 'str'],
|
||||
['reason', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
req.setHeader("Location", "%s/.." % req.prePathURL())
|
||||
return val
|
||||
|
||||
def op_save(self, op, req):
|
||||
fn = FormFn(self.xd.domain_save,
|
||||
[['dom', 'str'],
|
||||
['file', 'str']])
|
||||
deferred = fn(req.args, {'dom': self.dom.id})
|
||||
deferred.addCallback(self._op_save_cb, req)
|
||||
deferred.addErrback(self._op_save_err, req)
|
||||
return deferred
|
||||
|
||||
def _op_save_cb(self, val, req):
|
||||
return 0
|
||||
|
||||
def _op_save_err(self, err, req):
|
||||
req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
|
||||
return str(err)
|
||||
|
||||
def op_migrate(self, op, req):
|
||||
fn = FormFn(self.xd.domain_migrate,
|
||||
[['dom', 'str'],
|
||||
['destination', 'str'],
|
||||
['live', 'int']])
|
||||
deferred = fn(req.args, {'dom': self.dom.id})
|
||||
print 'op_migrate>', deferred
|
||||
deferred.addCallback(self._op_migrate_cb, req)
|
||||
deferred.addErrback(self._op_migrate_err, req)
|
||||
return deferred
|
||||
|
||||
def _op_migrate_cb(self, info, req):
|
||||
print '_op_migrate_cb>', info, req
|
||||
#req.setResponseCode(http.ACCEPTED)
|
||||
host = info.dst_host
|
||||
port = info.dst_port
|
||||
dom = info.dst_dom
|
||||
url = "http://%s:%d/xend/domain/%d" % (host, port, dom)
|
||||
req.setHeader("Location", url)
|
||||
print '_op_migrate_cb> url=', url
|
||||
return url
|
||||
|
||||
def _op_migrate_err(self, err, req):
|
||||
print '_op_migrate_err>', err, req
|
||||
req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
|
||||
return str(err)
|
||||
|
||||
def op_pincpu(self, op, req):
|
||||
fn = FormFn(self.xd.domain_pincpu,
|
||||
[['dom', 'str'],
|
||||
['cpu', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_cpu_bvt_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_cpu_bvt_set,
|
||||
[['dom', 'str'],
|
||||
['mcuadv', 'int'],
|
||||
['warpback', 'int'],
|
||||
['warpvalue', 'int'],
|
||||
['warpl', 'long'],
|
||||
['warpu', 'long']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_cpu_fbvt_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_cpu_fbvt_set,
|
||||
[['dom', 'str'],
|
||||
['mcuadv', 'int'],
|
||||
['warp', 'int'],
|
||||
['warpl', 'int'],
|
||||
['warpu', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_maxmem_set(self, op, req):
|
||||
fn = FormFn(self.xd.domain_maxmem_set,
|
||||
[['dom', 'str'],
|
||||
['memory', 'int']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
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.id})
|
||||
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.id})
|
||||
return val
|
||||
|
||||
def op_vifs(self, op, req):
|
||||
devs = self.xd.domain_vif_ls(self.dom.id)
|
||||
return [ dev.sxpr() for dev in devs ]
|
||||
|
||||
def op_vif(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vif_get,
|
||||
[['dom', 'str'],
|
||||
['vif', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def op_vbds(self, op, req):
|
||||
devs = self.xd.domain_vbd_ls(self.dom.id)
|
||||
return [ dev.sxpr() for dev in devs ]
|
||||
|
||||
def op_vbd(self, op, req):
|
||||
fn = FormFn(self.xd.domain_vbd_get,
|
||||
[['dom', 'str'],
|
||||
['vbd', 'str']])
|
||||
val = fn(req.args, {'dom': self.dom.id})
|
||||
return val
|
||||
|
||||
def render_POST(self, req):
|
||||
return self.perform(req)
|
||||
|
||||
def render_GET(self, req):
|
||||
op = req.args.get('op')
|
||||
if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd']:
|
||||
return self.perform(req)
|
||||
if self.use_sxp(req):
|
||||
req.setHeader("Content-Type", sxp.mime_type)
|
||||
sxp.show(self.dom.sxpr(), out=req)
|
||||
else:
|
||||
req.write('<html><head></head><body>')
|
||||
self.print_path(req)
|
||||
#self.ls()
|
||||
req.write('<p>%s</p>' % self.dom)
|
||||
if self.dom.console:
|
||||
cinfo = self.dom.console
|
||||
cid = str(cinfo.console_port)
|
||||
#todo: Local xref: need to know server prefix.
|
||||
req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
|
||||
% (cid, cid))
|
||||
req.write('<p><a href="%s">Connect to console</a></p>'
|
||||
% cinfo.uri())
|
||||
if self.dom.config:
|
||||
req.write("<code><pre>")
|
||||
PrettyPrint.prettyprint(self.dom.config, out=req)
|
||||
req.write("</pre></code>")
|
||||
self.form(req)
|
||||
req.write('</body></html>')
|
||||
return ''
|
||||
|
||||
def form(self, req):
|
||||
url = req.prePathURL()
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
req.write('<input type="submit" name="op" value="unpause">')
|
||||
req.write('<input type="submit" name="op" value="pause">')
|
||||
req.write('</form>')
|
||||
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
req.write('<input type="submit" name="op" value="destroy">')
|
||||
req.write('<input type="radio" name="reason" value="halt" checked>Halt')
|
||||
req.write('<input type="radio" name="reason" value="reboot">Reboot')
|
||||
req.write('</form>')
|
||||
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
req.write('<input type="submit" name="op" value="shutdown">')
|
||||
req.write('<input type="radio" name="reason" value="poweroff" checked>Poweroff')
|
||||
req.write('<input type="radio" name="reason" value="halt">Halt')
|
||||
req.write('<input type="radio" name="reason" value="reboot">Reboot')
|
||||
req.write('</form>')
|
||||
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
req.write('<br><input type="submit" name="op" value="save">')
|
||||
req.write(' To file: <input type="text" name="file">')
|
||||
req.write('</form>')
|
||||
|
||||
req.write('<form method="post" action="%s">' % url)
|
||||
req.write('<br><input type="submit" name="op" value="migrate">')
|
||||
req.write(' To host: <input type="text" name="destination">')
|
||||
req.write('<input type="checkbox" name="live" value="1">Live')
|
||||
req.write('</form>')
|
||||
@@ -5,7 +5,7 @@ from xen.xend.Args import FormFn
|
||||
from xen.xend import PrettyPrint
|
||||
from xen.xend import XendVnet
|
||||
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
|
||||
class SrvVnet(SrvDir):
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from xen.web import static
|
||||
|
||||
from xen.xend import XendRoot
|
||||
|
||||
from SrvDir import SrvDir
|
||||
from xen.web.SrvDir import SrvDir
|
||||
|
||||
class SrvXendLog(SrvDir):
|
||||
"""Xend log.
|
||||
|
||||
@@ -425,10 +425,10 @@ class BlkifController(DevController):
|
||||
for a domain.
|
||||
"""
|
||||
|
||||
def __init__(self, dctype, vm, recreate=False):
|
||||
def __init__(self, vm, recreate=False):
|
||||
"""Create a block device controller.
|
||||
"""
|
||||
DevController.__init__(self, dctype, vm, recreate=recreate)
|
||||
DevController.__init__(self, vm, recreate=recreate)
|
||||
self.backends = {}
|
||||
self.backendId = 0
|
||||
self.rcvr = None
|
||||
|
||||
@@ -66,6 +66,8 @@ class ChannelFactory:
|
||||
def __init__(self):
|
||||
"""Constructor - do not use. Use the channelFactory function."""
|
||||
self.notifier = xu.notifier()
|
||||
# Register interest in all virqs.
|
||||
# Unfortunately virqs do not seem to be delivered.
|
||||
self.bind_virq(VIRQ_MISDIRECT)
|
||||
self.bind_virq(VIRQ_TIMER)
|
||||
self.bind_virq(VIRQ_DEBUG)
|
||||
@@ -97,6 +99,7 @@ class ChannelFactory:
|
||||
|
||||
def main(self):
|
||||
"""Main routine for the thread.
|
||||
Reads the notifier and dispatches to channels.
|
||||
"""
|
||||
while True:
|
||||
if self.thread == None: return
|
||||
@@ -224,18 +227,23 @@ def channelFactory():
|
||||
return inst
|
||||
|
||||
class Channel:
|
||||
"""Chanel to a domain.
|
||||
Maintains a list of device handlers to dispatch requests to, based
|
||||
on the request type.
|
||||
"""
|
||||
|
||||
def __init__(self, factory, dom, local_port, remote_port):
|
||||
self.factory = factory
|
||||
self.dom = int(dom)
|
||||
# Registered devices.
|
||||
# Registered device handlers.
|
||||
self.devs = []
|
||||
# Devices indexed by the message types they handle.
|
||||
# Handlers indexed by the message types they handle.
|
||||
self.devs_by_type = {}
|
||||
self.port = self.factory.createPort(self.dom,
|
||||
local_port=local_port,
|
||||
remote_port=remote_port)
|
||||
self.closed = False
|
||||
# Queue of waiters for responses to requests.
|
||||
self.queue = ResponseQueue(self)
|
||||
# Make sure the port will deliver all the messages.
|
||||
self.port.register(TYPE_WILDCARD)
|
||||
@@ -298,11 +306,11 @@ class Channel:
|
||||
|
||||
|
||||
def registerDevice(self, types, dev):
|
||||
"""Register a device controller.
|
||||
"""Register a device message handler.
|
||||
|
||||
@param types: message types the controller handles
|
||||
@param types: message types handled
|
||||
@type types: array of ints
|
||||
@param dev: device controller
|
||||
@param dev: device handler
|
||||
"""
|
||||
if self.closed: return
|
||||
self.devs.append(dev)
|
||||
@@ -310,9 +318,9 @@ class Channel:
|
||||
self.devs_by_type[ty] = dev
|
||||
|
||||
def deregisterDevice(self, dev):
|
||||
"""Remove the registration for a device controller.
|
||||
"""Remove the registration for a device handler.
|
||||
|
||||
@param dev: device controller
|
||||
@param dev: device handler
|
||||
"""
|
||||
if dev in self.devs:
|
||||
self.devs.remove(dev)
|
||||
@@ -321,16 +329,20 @@ class Channel:
|
||||
del self.devs_by_type[ty]
|
||||
|
||||
def getDevice(self, type):
|
||||
"""Get the device controller handling a message type.
|
||||
"""Get the handler for a message type.
|
||||
|
||||
@param type: message type
|
||||
@type type: int
|
||||
@return: controller or None
|
||||
@rtype: device controller
|
||||
@rtype: device handler
|
||||
"""
|
||||
return self.devs_by_type.get(type)
|
||||
|
||||
def requestReceived(self, msg):
|
||||
"""A request has been received on the channel.
|
||||
Disptach it to the device handlers.
|
||||
Called from the channel factory thread.
|
||||
"""
|
||||
if DEBUG:
|
||||
print 'Channel>requestReceived>', self,
|
||||
printMsg(msg)
|
||||
@@ -340,7 +352,7 @@ class Channel:
|
||||
if dev:
|
||||
responded = dev.requestReceived(msg, ty, subty)
|
||||
elif DEBUG:
|
||||
print "Channel>requestReceived> No device", self,
|
||||
print "Channel>requestReceived> No device handler", self,
|
||||
printMsg(msg)
|
||||
else:
|
||||
pass
|
||||
@@ -348,6 +360,8 @@ class Channel:
|
||||
self.writeResponse(msg)
|
||||
|
||||
def writeRequest(self, msg):
|
||||
"""Write a request to the channel.
|
||||
"""
|
||||
if DEBUG:
|
||||
print 'Channel>writeRequest>', self,
|
||||
printMsg(msg, all=True)
|
||||
@@ -356,6 +370,8 @@ class Channel:
|
||||
return 1
|
||||
|
||||
def writeResponse(self, msg):
|
||||
"""Write a response to the channel.
|
||||
"""
|
||||
if DEBUG:
|
||||
print 'Channel>writeResponse>', self,
|
||||
printMsg(msg, all=True)
|
||||
@@ -364,6 +380,9 @@ class Channel:
|
||||
return 1
|
||||
|
||||
def readRequest(self):
|
||||
"""Read a request from the channel.
|
||||
Called internally.
|
||||
"""
|
||||
if self.closed:
|
||||
val = None
|
||||
else:
|
||||
@@ -371,6 +390,9 @@ class Channel:
|
||||
return val
|
||||
|
||||
def readResponse(self):
|
||||
"""Read a response from the channel.
|
||||
Called internally.
|
||||
"""
|
||||
if self.closed:
|
||||
val = None
|
||||
else:
|
||||
@@ -399,6 +421,10 @@ class Channel:
|
||||
return self.queue.call(msg, timeout)
|
||||
|
||||
def responseReceived(self, msg):
|
||||
"""A response has been received, look for a waiter to
|
||||
give it to.
|
||||
Called internally.
|
||||
"""
|
||||
if DEBUG:
|
||||
print 'Channel>responseReceived>', self,
|
||||
printMsg(msg)
|
||||
@@ -407,7 +433,6 @@ class Channel:
|
||||
def virq(self):
|
||||
self.factory.virq()
|
||||
|
||||
|
||||
class Response:
|
||||
"""Entry in the response queue.
|
||||
Used to signal a response to a message.
|
||||
@@ -463,7 +488,8 @@ class ResponseQueue:
|
||||
return r
|
||||
|
||||
def response(self, mid, msg):
|
||||
"""Process a response.
|
||||
"""Process a response - signals any waiter that a response
|
||||
has arrived.
|
||||
"""
|
||||
try:
|
||||
self.lock.acquire()
|
||||
|
||||
@@ -326,8 +326,8 @@ class ConsoleController(DevController):
|
||||
"""Device controller for all the consoles for a domain.
|
||||
"""
|
||||
|
||||
def __init__(self, dctype, vm, recreate=False):
|
||||
DevController.__init__(self, dctype, vm, recreate=recreate)
|
||||
def __init__(self, vm, recreate=False):
|
||||
DevController.__init__(self, vm, recreate=recreate)
|
||||
self.rcvr = None
|
||||
|
||||
def initController(self, recreate=False, reboot=False):
|
||||
|
||||
@@ -9,7 +9,7 @@ from messages import msgTypeName, printMsg, getMessageType
|
||||
DEBUG = 0
|
||||
|
||||
class CtrlMsgRcvr:
|
||||
"""Dispatcher class for messages on a control channel.
|
||||
"""Utility class to dispatch messages on a control channel.
|
||||
Once I{registerChannel} has been called, our message types are registered
|
||||
with the channel. The channel will call I{requestReceived}
|
||||
when a request arrives if it has one of our message types.
|
||||
@@ -105,65 +105,32 @@ class CtrlMsgRcvr:
|
||||
if self.channel:
|
||||
self.channel.deregisterDevice(self)
|
||||
|
||||
class DevControllerType:
|
||||
"""Abstract class for device controller types.
|
||||
"""
|
||||
|
||||
def __init__(self, type):
|
||||
self.type = type
|
||||
|
||||
def getType(self):
|
||||
"""Get the device controller type name.
|
||||
"""
|
||||
return self.type
|
||||
|
||||
def createDevController(self, vm, recreate=False):
|
||||
"""Create a device controller for a domain.
|
||||
Must be implemented in subclass.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
class SimpleDevControllerType(DevControllerType):
|
||||
"""Device controller type that simply wraps a controller
|
||||
class and uses its constructor to create instances.
|
||||
"""
|
||||
|
||||
def __init__(self, type, devControllerClass):
|
||||
DevControllerType.__init__(self, type)
|
||||
self.devControllerClass = devControllerClass
|
||||
|
||||
def createDevController(self, vm, recreate=False):
|
||||
"""Create a device controller for a domain.
|
||||
"""
|
||||
ctrl = self.devControllerClass(self, vm, recreate=recreate)
|
||||
ctrl.initController(recreate=recreate)
|
||||
return ctrl
|
||||
|
||||
class DevControllerTable:
|
||||
"""Table of device controller types, indexed by type name.
|
||||
"""Table of device controller classes, indexed by type name.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.controllerTypes = {}
|
||||
self.controllerClasses = {}
|
||||
|
||||
def getDevControllerType(self, type):
|
||||
return self.controllerTypes.get(type)
|
||||
def getDevControllerClass(self, type):
|
||||
return self.controllerClasses.get(type)
|
||||
|
||||
def addDevControllerType(self, dctype):
|
||||
self.controllerTypes[dctype.getType()] = dctype
|
||||
return dctype
|
||||
def addDevControllerClass(self, klass):
|
||||
self.controllerClasses[klass.getType()] = klass
|
||||
|
||||
def delDevControllerType(self, type):
|
||||
if type in self.controllerTypes:
|
||||
del self.controllerTypes[type]
|
||||
def delDevControllerClass(self, type):
|
||||
if type in self.controllerClasses:
|
||||
del self.controllerClasses[type]
|
||||
|
||||
def createDevController(self, type, vm, recreate=False):
|
||||
dctype = self.getDevControllerType(type)
|
||||
if not dctype:
|
||||
klass = self.getDevControllerClass(type)
|
||||
if not klass:
|
||||
raise XendError("unknown device type: " + type)
|
||||
return dctype.createDevController(vm, recreate=recreate)
|
||||
return klass.createDevController(vm, recreate=recreate)
|
||||
|
||||
def getDevControllerTable():
|
||||
"""Singleton constructor for the controller table.
|
||||
"""
|
||||
global devControllerTable
|
||||
try:
|
||||
devControllerTable
|
||||
@@ -171,12 +138,11 @@ def getDevControllerTable():
|
||||
devControllerTable = DevControllerTable()
|
||||
return devControllerTable
|
||||
|
||||
def addDevControllerType(dctype):
|
||||
return getDevControllerTable().addDevControllerType(dctype)
|
||||
|
||||
def addDevControllerClass(name, klass):
|
||||
ty = SimpleDevControllerType(name, klass)
|
||||
return addDevControllerType(ty)
|
||||
"""Add a device controller class to the controller table.
|
||||
"""
|
||||
klass.name = name
|
||||
getDevControllerTable().addDevControllerClass(klass)
|
||||
|
||||
def createDevController(name, vm, recreate=False):
|
||||
return getDevControllerTable().createDevController(name, vm, recreate=recreate)
|
||||
@@ -189,17 +155,29 @@ class DevController:
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, dctype, vm, recreate=False):
|
||||
self.dctype = dctype
|
||||
name = None
|
||||
|
||||
def createDevController(klass, vm, recreate=False):
|
||||
"""Class method to create a dev controller.
|
||||
"""
|
||||
ctrl = klass(vm, recreate=recreate)
|
||||
ctrl.initController(recreate=recreate)
|
||||
return ctrl
|
||||
|
||||
createDevController = classmethod(createDevController)
|
||||
|
||||
def getType(klass):
|
||||
return klass.name
|
||||
|
||||
getType = classmethod(getType)
|
||||
|
||||
def __init__(self, vm, recreate=False):
|
||||
self.destroyed = False
|
||||
self.vm = vm
|
||||
self.deviceId = 0
|
||||
self.devices = {}
|
||||
self.device_order = []
|
||||
|
||||
def getType(self):
|
||||
return self.dctype.getType()
|
||||
|
||||
def getDevControllerType(self):
|
||||
return self.dctype
|
||||
|
||||
@@ -222,6 +200,14 @@ class DevController:
|
||||
# Redefinitions must have the same arguments.
|
||||
|
||||
def initController(self, recreate=False, reboot=False):
|
||||
"""Initialise the controller. Called when the controller is
|
||||
first created, and again after the domain is rebooted (with reboot True).
|
||||
If called with recreate True (and reboot False) the controller is being
|
||||
recreated after a xend restart.
|
||||
|
||||
As this can be a re-init (after reboot) any controller state should
|
||||
be reset. For example the destroyed flag.
|
||||
"""
|
||||
self.destroyed = False
|
||||
if reboot:
|
||||
self.rebootDevices()
|
||||
@@ -229,12 +215,19 @@ class DevController:
|
||||
def newDevice(self, id, config, recreate=False):
|
||||
"""Create a device with the given config.
|
||||
Must be defined in subclass.
|
||||
Called with recreate True when the device is being recreated after a
|
||||
xend restart.
|
||||
|
||||
@return device
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def createDevice(self, config, recreate=False, change=False):
|
||||
"""Create a device and attach to its front- and back-ends.
|
||||
If recreate is true the device is being recreated after a xend restart.
|
||||
If change is true the device is a change to an existing domain,
|
||||
i.e. it is being added at runtime rather than when the domain is created.
|
||||
"""
|
||||
dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate)
|
||||
dev.init(recreate=recreate)
|
||||
self.addDevice(dev)
|
||||
@@ -252,7 +245,12 @@ class DevController:
|
||||
|
||||
def destroyDevice(self, id, change=False, reboot=False):
|
||||
"""Destroy a device.
|
||||
May be defined in subclass."""
|
||||
May be defined in subclass.
|
||||
|
||||
If reboot is true the device is being destroyed for a domain reboot.
|
||||
|
||||
The device is not deleted, since it may be recreated later.
|
||||
"""
|
||||
dev = self.getDevice(id)
|
||||
if not dev:
|
||||
raise XendError("invalid device id: " + id)
|
||||
@@ -260,12 +258,18 @@ class DevController:
|
||||
return dev
|
||||
|
||||
def deleteDevice(self, id, change=True):
|
||||
"""Destroy a device and delete it.
|
||||
Normally called to remove a device from a domain at runtime.
|
||||
"""
|
||||
dev = self.destroyDevice(id, change=change)
|
||||
self.removeDevice(dev)
|
||||
|
||||
def destroyController(self, reboot=False):
|
||||
"""Destroy all devices and clean up.
|
||||
May be defined in subclass."""
|
||||
May be defined in subclass.
|
||||
If reboot is true the controller is being destroyed for a domain reboot.
|
||||
Called at domain shutdown.
|
||||
"""
|
||||
self.destroyed = True
|
||||
self.destroyDevices(reboot=reboot)
|
||||
|
||||
@@ -394,6 +398,13 @@ class Dev:
|
||||
"""Initialization. Called on initial create (when reboot is False)
|
||||
and on reboot (when reboot is True). When xend is restarting is
|
||||
called with recreate True. Define in subclass if needed.
|
||||
|
||||
Device instance variables must be defined in the class constructor,
|
||||
but given null or default values. The real values should be initialised
|
||||
in this method. This allows devices to be re-initialised.
|
||||
|
||||
Since this can be called to re-initialise a device any state flags
|
||||
should be reset.
|
||||
"""
|
||||
self.destroyed = False
|
||||
|
||||
@@ -404,7 +415,7 @@ class Dev:
|
||||
pass
|
||||
|
||||
def reboot(self):
|
||||
"""Reconnect device when the domain is rebooted.
|
||||
"""Reconnect the device when the domain is rebooted.
|
||||
"""
|
||||
self.init(reboot=True)
|
||||
self.attach()
|
||||
@@ -435,6 +446,9 @@ class Dev:
|
||||
If change is True notify destruction (runtime change).
|
||||
If reboot is True the device is being destroyed for a reboot.
|
||||
Redefine in subclass if needed.
|
||||
|
||||
Called at domain shutdown and when a device is deleted from
|
||||
a running domain (with change True).
|
||||
"""
|
||||
self.destroyed = True
|
||||
pass
|
||||
|
||||
@@ -376,8 +376,8 @@ class NetifController(DevController):
|
||||
"""Network interface controller. Handles all network devices for a domain.
|
||||
"""
|
||||
|
||||
def __init__(self, dctype, vm, recreate=False):
|
||||
DevController.__init__(self, dctype, vm, recreate=recreate)
|
||||
def __init__(self, vm, recreate=False):
|
||||
DevController.__init__(self, vm, recreate=recreate)
|
||||
self.channel = None
|
||||
self.rcvr = None
|
||||
self.channel = None
|
||||
|
||||
@@ -240,10 +240,10 @@ class UsbifController(DevController):
|
||||
for a domain.
|
||||
"""
|
||||
|
||||
def __init__(self, dctype, vm, recreate=False):
|
||||
def __init__(self, vm, recreate=False):
|
||||
"""Create a USB device controller.
|
||||
"""
|
||||
DevController.__init__(self, dctype, vm, recreate=recreate)
|
||||
DevController.__init__(self, vm, recreate=recreate)
|
||||
self.backends = {}
|
||||
self.backendId = 0
|
||||
self.rcvr = None
|
||||
|
||||
Whitespace-only changes.