mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
bitkeeper revision 1.1108.35.2 (4108f181qIC17s1k7tUAzAMnlIZwBA)
Add support for getting the xend log. Needed response headers and mime-types in the xend client code. Add command groups in xm help.
This commit is contained in:
1 parent
08aa92db57
commit
7aeeeea161
9 files changed
+179
-80
No files matched your search
@@ -130,7 +130,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 +175,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 +196,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 +224,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 +234,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 +263,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 +278,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 +309,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)
|
||||
@@ -397,9 +384,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 +392,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():
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
+97
-21
@@ -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,57 @@ 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 ProgHelp(Prog):
|
||||
|
||||
name = "help"
|
||||
@@ -157,8 +223,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 +286,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']
|
||||
@@ -512,7 +578,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):
|
||||
@@ -533,7 +599,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.
|
||||
@@ -550,9 +616,19 @@ 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)
|
||||
|
||||
def main(args):
|
||||
xm.main(args)
|
||||
@@ -9,7 +9,8 @@ import time
|
||||
from xen.xend.XendClient import server
|
||||
from xen.xm.opts import *
|
||||
|
||||
DOM0 = 'Domain-0'
|
||||
DOM0_NAME = 'Domain-0'
|
||||
DOM0_ID = '0'
|
||||
|
||||
gopts = Opts(use="""[options] [DOM]
|
||||
|
||||
@@ -38,8 +39,9 @@ gopts.opt('reboot', short='R',
|
||||
|
||||
def shutdown(opts, doms, mode, wait):
|
||||
if doms == None: doms = server.xend_domains()
|
||||
if DOM0 in doms:
|
||||
doms.remove(DOM0)
|
||||
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:
|
||||
|
||||